c++ handling derived class that's self referencing - c++

So suppose I have a tree class like this in c++
class Node{
void addChild(Node*);
/*obvious stuff*/
protected:
Node* parent;
vector<Node*> children
}
class specialNode : public Node{
void addChild(specialNode*);
/*obvious stuff*/
/*special stuff*/
}
Now whenever I access the children in specialTree, I obviously get Node*, not specialNode*.
But this specialNode* has member variables and functions that Node doesn't have.
I can force specialNode to only have take specialNode as children and otherwise break in compile time,
but I still get Node* when accessing children/parent, and I have to cast it whenever I want to use special functions, even in specialNode functions.
Is there any clever, or just any better way to go about this?
Other than literally casting every time?

If you only need SpecialNode objects in your tree (and just want to encapsulate all generic tree functionality in Node) you can make Node a so called "mix-in" class like
template <class N>
class Node : public N {
public:
void addChild(Node<N>*);
protected:
Node<N>* parent;
vector<Node<N>*> children;
};
class SpecialNodeBase {
// Here comes all "special" data/methods for your "special" tree
};
typedef Node<SpecialNodeBase> SpecialNode;
After that you can construct a tree of SpecialNode objects and use all methods from SpecialNodeBase as well as additional tree-managing functions from Node

Because addChild function in your child class is not polymorphism, make it virtual, but overloading functions across base/child members is not allowed, so we have to change the addChild parameter in the child class:
class Node{
virtual void addChild(Node*);
...
}
class specialNode : public Node{
virtual void addChild(Node*);
...
}
Now, it should work.
If you want to access to the childeren variable from the child class (specialNode class), you should cast it. For example:
specialNode* var = static_cast<specialNode*>(children[i]);
Since we declared addChild as a virtual function, then we should use dynamic_cast instead of static_cast if we aren't sure that children[i] is always an instance of specialNode class, and thus it is better to use dynamic_cast:
specialNode* var = dynamic_cast<specialNode*>(children[i]);
if(var != NULL)
{
//...
}

If I understand correctly, the "Mix-in" class solution won't allow you to call addChild from functions implemented by SpecialNodeBaseClass.
You can actually do the following:
template <class recursiveT>
class Base {
public:
Base(dataType data) { populate children with data; }
void addChild() { something base class appropriate; }
protected:
std::vector<recursiveT> children;
};
class Derived: public Base<Derived> {
public:
/* note: the constructor here will actually call the
constuctor of the base class */
Derived(dataType data) : Base<Derived>(data) {}
/* other special functions go here. */
};
This may look a little crazy, but it compiles cleanly for me on several GCC versions so I'm inclined to believe it's not totally wrong-headed. You should now be able to call the functions of Base from inside Derived.

You will definitely have to cast the Node * to a specialNode * at some point, but you can make this clean and easy to manage by doing this in only one place. You could add a member function, say getParent and override it in specialNode, like this:
class Node {
...
virtual Node *getParent() {
return parent;
}
};
class specialNode : public Node {
...
specialNode *getParent() {
return dynamic_cast<specialNode *>(parent);
}
};
Of course, this is assuming that specialNodes always have other specialNodes as parent/children. If you mix Nodes and specialNodes, this obviously won't work.

Related

Getters in recursive class with pointers to other instances of the class

For a school project, I need to build a BinarySearchTree for a tuple of index and value of type T and I decided to make it using left and right child pointers (to other instances but bear with me).
To make the class a bit more realistic and readable, I built 3 different classes: Tree, BinaryTree, and BinarySearchTree with inheritance.
I declared the getter and the setter of the left and right children in the BinaryTree class and the class looks like this:
template <typename T>
class ArbreBinaire : public Arbre<T>
{
private:
ArbreBinaire<T>* _leftChild;
ArbreBinaire<T>* _rightChild;
public:
ArbreBinaire(lu index = 0, T element = T(0), ArbreBinaire<T>* lchild = nullptr, ArbreBinaire<T>* rchild = nullptr) :
Arbre<T>(index, element), _leftChild(lchild), _rightChild(rchild) {};
virtual ArbreBinaire<T>* getLC() const { return _leftChild; }
virtual ArbreBinaire<T>* getRC() const { return _rightChild;}
void setLC(ArbreBinaire<T>* lc) { _leftChild = lc; lc->setParent(this); }
void setRC(ArbreBinaire<T>* rc) { _rightChild = rc; rc->setParent(this); }
virtual ~ArbreBinaire() = default;
};
And in my BinarySearchTree, in a few places I need to go through my tree (to insert or search for exemple).
So here comes finally my question: What is the best way to get the left child of my object, which is of type BinarySearchTree and to keep the continuity (BST that has BST left child and BST right child)
I thought of multiple options:
virtual getter and setter and redefining it in every derived class but there are 2 other "problems" with that solution.
Should I have 2 other members in my BST, which would be of type BST* and basically point to the same object than the ones in my BinaryTree ?
Should I just redefine my getters to return a dynamic_cast version like this : BST<T>* getLC() { return dynamic_cast<BST<T>*> (this->BinaryTree::getLC()) } ?
Putting all my members, getters and setters in my BST class (but that goes opposite to the definition of a BinaryTree, the base class : a BinaryTree with no children is not a BinaryTree)
3.Just casting every time i need to get my left or right child
4.Casting everytime i need to use a method in BST (derived class) ?
5. Any other suggestions?

Remove dynamic_cast in derived class of tree node

I have a class which is a node of a tree, called Node. I need to create a DerivedNode class type which has some extra functionality. The problem is that Node has a vector of Node* as a member variable, so when DerivedNode inherits from Node, it inherits this vector. I've created a basic example showing the issue:
#include <iostream>
#include <vector>
class Node {
public:
Node(int value_) : value(value_) {}
int foo() { return value; }
virtual void add(Node* new_node) {
children.push_back(new_node);
}
protected:
std::vector<Node*> children;
int value;
};
class DerivedNode : public Node {
public:
DerivedNode(int value_) : Node(value_) {}
int bar() { return value*2; }
// Ensures we only add children of type DynamicNode*
virtual void add(DerivedNode* new_node) {
children.push_back(new_node);
}
void print() {
for (size_t i = 0; i < children.size(); ++i) {
std::cout << dynamic_cast<DerivedNode*>(children[i])->bar() << std::endl;
}
}
};
int main() {
DerivedNode* child_a = new DerivedNode(5);
DerivedNode* child_b = new DerivedNode(6);
DerivedNode parent(1);
parent.add(child_a);
parent.add(child_b);
parent.print();
delete child_a;
delete child_b;
}
My question is, how can I do this without the dynamic_cast? My actual code is far more complex which means that there are dynamic casts everywhere.
First add function in derived class is totally useless, it does not override add function from base class, it overloads it. In such way you still can add Node*'s to the derived class. To prevent this you should override add(Node*) as private.
If you does not like dynamic cast, you may use static cast instead
or
You may have virtual bar in base class that does not do anything
or
you can cast the vector itself (the whole thing) and assign to reference or pointer to std::vector DerivedNode*
You can't have it both ways. You either have IS-A principle reflected in the design of your classess, or you don't. If DerivedNode is Node, than the vector of Nodes should be indistinguishable from vector of DerivedNodes - and no casts are neccessary. If this can not be achieved, that you simply can not use vector of base pointers.
Any dynamic_cast in production code for me is a hard block for any review, as it clearly violates the basic design principles.

OO design for intrusive data structure

I'm writing an intrusive linked list
class ListAlgorithm {
ListNode& next(ListNode& n) {
//returns an object of type ListNode linked to n.
}
};
Users usually want to add some features (such as some additional data) on ListNode like this:
class UserNode : public ListNode {
void operationOnUserData();
int userData;
};
Then users have to downcast ListNode returned by 'next' into UserNode. It is inconvenient. Thus, I tried to make ListAlgorithm a template class :
//U extends ListNode
template<class U>
class ListAlgorihtm {
U& next(U& u);
};
But then I have to upcast u into ListNode inside the method 'next' because class U could accidentally hide some members of ListNode that ListAlgorithm uses. This is error-prone because I could forget the upcast and compiler will not warn about that. I have to downcast ListNode into U again for the return value but it is safe because 'next' takes an instance u of U and the return value is something from u.
Another trial is
//U extends ListNode
template<class U>
class ListAlgorhtm {
U& next(ListNode& n);
};
In this case, the upcast problem is not there, but I have to downcast ListNode into U for the return value and it is not safe because it is not sure that n is an instance of U. It could be an instance of another type extending ListNode.
What is the best solution in this case? I think this is a very elementary design problem and I'd like to know what kind of material I have to study for basic OO design like this.
Your actual problem here is that you allow users to subclass ListNode and mess with its semantics by adding arbitrary data and operations to ListNode objects through subclassing. This therefore makes it necessary for the user to interpret the ListNode& return values of actual ListNode methods as something that those return values are not, semantically speaking.
This problem of a semantic nature is reflected in how tedious your code suddenly becomes, with casts and templating of an unrelated class (ListAlgorithm) which is due to your problem "propagating" and infecting other parts of your code.
Here's a solution: a ListNode object should not be allowed to also be a UserNode object. However, it should be allowed to have, to carry with it a UserData object that can be retrieved and manipulated.
In other words, your list becomes a simple container template, like std::list, and the users can specify the operations and data members that they need as part of the definition of the class they use as the template argument.
class IListNode
{
public:
// whatever public methods you want here
protected:
// pure virtual methods maybe?
};
class ListNode : public IListNode
{
// List node class, no data
};
template<class UserDataType>
class ListNodeWithData : public IListNode
{
private:
UserDataType data;
public:
ListNodeWithData <UserDataType>(UserDataType &data) :
data(data)
{ }
const UserDataType& getData() {
return data;
}
};
class ListAlgorithm
{
public:
template<class UserDataType>
ListNodeWithData<UserDataType>& next(const ListNodeWithData<UserDataType>& node) {
// Do stuff
}
ListNode& next(const ListNode& node) {
// Do stuff, which may be very similar to the stuff done above
// in which case you may want to prefer to just define the
// method below, and remove this one and the one above:
}
// You should define either this method or the two above, but having
// them all is possible too, if you find a use for it
IListNode& next(const IListNode& node) {
// Do generic stuff
}
};
As far as the size of the resulting classes is concerned, I just know it will increase if you use virtual methods in IListNode.
As far as the issue you raise goes, any time you want to operate on members of a class and avoid hiding by a derived class, just make sure your operations are on the base, so
template<class U>
class ListAlgorihtm {
public:
U& next(U& u) {
return static_cast<U&>(return nextNode(u));
}
private:
ListNode& nextNode(ListNode& n);
};
That said, you have a lot of options for this problem set. The Boost library has an "intrusive" library that embeds node information either as base_hook (as a base of the user data) or member_hook (as a member of the class, which avoids some of the problems you describe). Check it out at http://www.boost.org/doc/libs/1_57_0/doc/html/intrusive.html.

Should I inherit a nested class within a derived class in c++?

Could (Edit: Should) I do something like this?
Edit:
I'll try asking about an example that may be better suited to this inheritence scheme. Note this isn't a working class, just for the concept.
template<typename T>
class Tree {
protected:
class Node {
Node* _parent;
T _data
};
};
template<typename T>
class BinaryTree: public Tree {
private:
class BinaryNode: public Tree<T>::Node {
Node *_left, *_right;
};
};
This way of constructing parallel class hierarchies is not uncommon. However, it is more common to hide the nested derived class as an implementation detail that should be encapsulated, i.e. the BiIterator in your example would be in the private: section.
However, Iterator is not a good example because of object slicing: even if BiIterator remains public, this seemingly innocent code is incorrect:
BidirectionalList biList;
// This would slice off BiIterator's functionality
Iterator iter(biList.get_iterator());
while (iter.has_next()) {
...
}
A better example would be if the base class member function took a reference or a pointer to an object of a nested class defined in the base, and a derived class would pass its derived nested class for it:
class Task {
public:
class Worker {
public virtual void work()=0;
}
void run(Worker& w);
};
class SpecialTask : public Task {
private:
class SpecialWorker : public Worker {
public virtual void work() {
...
}
};
public:
void do_something() {
SpecialWorker w;
run(w); // Passes SpecialWorker to run() of base class
}
};
There is nothing illegal about what you're doing so you could do it.
As far as should you, that's less clear cut.
But for this example I do think the answer is clear. When implementing C++ containers they decided to implement iterator separately from all their container classes. Benefiting from their wisdom wouldn't be a bad choice in this case.
EDIT:
For a container structure your contained object type should be templatized. For my proof I'd again reference C++ container design.
But here I think it's much more clear cut. If you write an excellent Tree or BinaryTree class that's templatized, you could use that over and over in all the code you write for the rest of your life. Why not take advantage of that?
(Just a word of caution you might be reinventing the wheel here. Have a look at this: http://www.cplusplus.com/reference/algorithm/make_heap/)

Curious circular inheritance with mix-ins in C++

What is a good way to unscramble the circular inheritance here?
class Node {
// ...
public:
list<Node*> neighbors() { /* ... */ }
void update() { }
}
template<class NodeType>
class HasImportance : public virtual NodeType {
double m_importance = 0.0;
public:
void receive_importance(double imp) { /* ... */ }
void give_importance() {
for (auto neighbor : this->neighbors())
neighbor->receive_importance(m_importance /* ... */);
}
};
class TrafficLight : public HasImportance<TrafficLight>, virtual Node {
public:
list<TrafficLight*> neighbors() { ... }
void update() { give_importance(); /* ... */ }
};
It fails (gcc 4.7.0) because TrafficLight is an incomplete type
when HasImportance tries to inherit from it.
The real problem is that HasImportance needs to know the type returned by
neighbors(). If HasImportance inherits from
Node, then it thinks neighbors() returns a list of
Node*, not TrafficLight*, and consequently doesn't
know that it can call receive_importance() on the items. Similar
problem if HasImportance doesn't inherit at all.
BTW, what I'm trying to do is make a few mix-ins to help define a variety of
different kinds of graphs easily and to unit-test each mix-in separately. For
example, I should be able to define the node class for a graph of traffic lights by just writing
something like class TrafficLight : public HasImportance, HasState<3>,
virtual Node { }.
I've come up with three ways to solve this, but all seem ugly. (1)
static_cast<NodeType*>. (2) TrafficLight passes its
this to HasImportance in its constructor. This way,
HasImportance doesn't need to inherit at all; it just stores a
pointer to (ahem) itself, and the template parameter provides the type of the
pointer. (3) Make Node a class template, like this:
template<class NodeType>
class Node {
public:
list<NodeType*> neighbors() { /* ... */ }
}
class TrafficLight : public HasImportance<Node<TrafficLight>> { /* ... */ }
That compiles and it doesn't introduce a gratuitous copy of this,
but it seems…a little too curious.
Is there a code smell here? Should I approach these graphs in a completely
different way?
(3) but a bit differently.
template <class NodeType>
class Node { ... };
template<class NodeType>
class HasImportance : public virtual Node<NodeType> { ... };
class TrafficLight : public HasImportance<TrafficLight> { ... };
Looks entirely straightforward to me, not more curious than the CRTP itself.