Re: Choosing between public and private inheritance
In article <xtxFl.1080$b11.890@nwrddc02.gnilink.net>,
"Dennis Jones" <djones@nospam.com> wrote:
Hi,
I have created a couple of template classes to model tree structures. The
base class represents a generic tree structure, and derived classes provide
modified interfaces and implementations:
template <typename T>
class GenericTree
{
public:
typedef treenode<T> node_type;
class ChildIterator_t
{
};
};
template <typename Key, typename T>
class MapTree : private GenericTree<T>
{
public:
typedef GenericTree<T> tree_type;
typedef Key key_type;
typedef T mapped_type;
typedef tree_type::node_type node_type;
typedef tree_type::ChildIterator_t ChildIterator_t;
void AddChild( const key_type &parent_key,
const key_type &key,
const mapped_type &Item )
{
node_type *ParentNode = get ParentNode from parent_key
AddChild( ParentNode, key, Item );
}
protected:
void AddChild( node_type *ParentNode,
const key_type key,
const mapped_type &Item )
{
}
};
typedef MapTree<int, MySpecialType> map_tree_type;
class MySpecialTree : private map_tree_type
{
public:
typedef map_tree_type inherited;
typedef inherited::node_type node_type;
typedef map_tree_type::ChildIterator_t ChildIterator_t;
void AddChild( node_type *ParentNode,
const key_type key,
const mapped_type &Item )
{
inherited::AddChild( ParentNode, key, Item );
}
};
Note that I've used private inheritance to model the
"implemented-in-terms-of" relationship between the classes, rather than
public inheritance modelling an "is-a" relationship.
Private inheritance seemed to make sense at the time, but as I begin to use
the MySpecialTree class, I often find myself needing to use methods that
exist at higher levels of the hierarchy, and the only way to do that with
private inheritance is to re-implement the methods in terms of the ancestor
class(es) (see AddChild). The same goes for typedefs (see node_type and
ChildIterator_t). This seems like a big waste of time and effort . . . not
to mention the mess it makes from what seems like a lot of unncesssary
declarations.
So, here's my question: how do I decide whether to use public or private
inheritance? If I switch to public inheritance, all of the extra
declarations and method implementations can go away. On the other hand, I'm
not sure public inheritance is what I want either, since the derived class
interfaces may be different from those of their ancestors.
What criteria should one use when making this kind of a design decision?
Public inheritance assumes substitutability:
[http://preview.tinyurl.com/w3car]
Can a MapTree<Key, T> be use anywhere a GenericTree<T> can be used? Can
you use a MySpecialTree anywhere you are using a MapTree<int,
MySpecialType>?
Are there even functions in your code that pass GenericTree<T> or
MapTree<int, MySpecialType> by reference or pointer?