Edited Shorter Question: When using a pointer to an abstract class, how can I call methods of the actual type of the object it points to?
I have an abstract BaseTree
class with a public
virtual BaseTree const& operator[](NodeIndex const& poss) const = 0;
where NodeIndex
is in practice std::vector<unsigned int>
. I have also a TreeBasicIterator
class which includes
public:
/// Access the tree to which m_tree points
BaseTree& operator*() const
{
//checking...
return (*m_tree)[*this];
}
private:
/// the tree the current iterator refers to
BaseTree* m_tree=nullptr;
Problem (I think it is the crux of my initial question below):
How can I use the methods of the class corresponding to the actual type of *m_tree? For now, when dereferencing my iterator, I can only use methods of the abstract class BaseTree
.
I would like to avoid making TreeBasicIterator
a template (see the initial question below).
Initial Question
As many (relatively new?) users of C++, I would like to write
virtual typedef something my_virtual_type;
inside classes definitions. Unfortunately it is not possible...
The most popular alternative seems to be templates, as for instance in alternative to virtual typedef which provides a nice sum up.
However I am not sure it covers everything a virtual typedef would. I present below a problem, for which I would like to have virtual typedefs. I have a (temporary?) working solution using overloading and not templates.
I want to create a fancy tree structure, including iterators.
1) I define a NodeIndex
type, ancestor of my future iterators. (NodeIndex
is in my case std::vector<unsigned int>
, but it doesn't matter.)
2) I define an abstract BaseTree
class, used in my iterators bellow. The class includes in particular virtual methods which returns NodeIndex
indexes to move in the tree (e.g. NodeIndex begin()
), and operator[](NodeIndex const&)
.
3) I define a TreeBasicIterator
class, inheriting from NodeIndex
, which for coherence purpose includes a const reference to a BaseTree
, and implements various iterators methods (making use of the virtual methods provided by BaseTree
).
(I have actually two classes: TreeBasicIterator
, and Const_TreeBasicIterator
with a const reference to a const BaseTree
; I use preprocessor macros to mimic a template based on const-ness, but this is another problem.)
4) I have defined a TreeNode<T>
template class (T
is the node content), inheriting from BaseTree
. For now its begin()
method returns a NodeIndex
, and its operator[]
takes a NodeIndex
as argument, and everything works fine.
5) However I want to include my TreeBasicIterator
in my TreeNode
class. I would like to include a
virtual typedef NodeIndex Iterator;
in my BaseTree
class, and modify the virtual begin()
method signature to Iterator begin()
.
Then TreeNode
would include a
virtual typedef TreeBasicIterator Iterator;
its begin()
method signature would be Iterator begin()
,
and everything would be hopefully fine :)
6) I do not wish to use templates on TreeBasicIterator
: it is now compiled once for all.
Making BaseTree
a template would make TreeBasicIterator
a template, and so loose a part of the benefits of the abstraction in BaseTree
.
Instanciating BaseTree
with NodeIndex
as Iterator
type would be superfluous: in practice nobody would inherit from that particular instance.
7) Prospective:
I will use trees with a fixed or rarely modified structure, but more frequently modified node contents, and even much more frequently read accesses. To optimize access, I intend to further derive from TreeNode
a TreeVector
class, which will include a sorted exhaustive std::vector
of NodeIndex
(or BasicTreeIterator
?) indexes. The Iterator
virtual type in TreeVector
would be std::iterator.
8) Current (temporary?) partially working solution:
TreeNode
defines (via a usual typedef
) an Iterator
type (my TreeBasicIterator
class). It does not override an Iterator
type from BaseTree
, but it could.
BaseTree
has a NodeIndex begin() const
method, which is both un-hidden, and overloaded in TreeNode
by a Iterator begin() const
method. It is not overridden.
Similarly, I have a NodeIndex next_index(NodeIndex) const
in BaseTree
, which is both un-hidden, and overloaded in TreeNode
by a Iterator next_index(Iterator) const
method.