C++: Should a tree root use inheritance over composition? - c++

I have a tree-like data structure that I've set up like this:
class Root; // forward declaration
class Tree {
public:
void addChildren(Root &r, ...) { childA = r.nodeSpace.allocate(); ... }
// tons of useful recursive functions here
private:
Tree *childA, *childB, *childC;
Tree *parent;
int usefulInt;
};
class Root : public Tree {
friend class Tree; // so it can access our storage
public:
private:
MemoryPool<Tree> nodeSpace;
};
I really like this structure, because
I can call all the recursive functions defined on Tree on Root as well, without having to copy-paste them over.
Root owns the storage, so whenever it passes out of scope, that's how I define the tree as no longer being valid.
But then I realized a problem. Someone might inadvertently call
Tree *root = new Root();
delete root; // memory leak! Tree has no virtual destructor...
This is not an intended usage (any ordinary usage should have Root on the stack). But I am open to alternatives. Right now, to solve this, I have three proposals:
Add virtual destructor to Tree. I would prefer not doing this because of the overhead as the tree can have many, many nodes.
Do not let Root inherit from Tree but instead have it define its own Tree member. Creates a little indirection, not too terrible, can still call the tons of useful recursive functions in Tree by doing root.tree().recursive().
Forbid assignments like Tree *root = new Root();. I have no idea if this is even possible or discouraged or encouraged. Are there compiler constructs?
Something else?
Which one of these should I prefer? Thank you very much!

The root node class (or any other node class) should not be an interface class. Keep it private and then inheritance without dynamic polymorphism (virtual) is not dangerous because the user will never see it.
Forbid assignments like Tree *root = new Root();. I have no idea if this is even possible or discouraged or encouraged. Are there compiler constructs?
This would be done by having Root inherit from Tree as a private base class.

Related

How to decide which methods belong where? C++

I finished writing an AVL tree, and one of the things that bothered me when programming it is deciding which methods belong to which class:
template <class ValueType,class CompareFunction>
class avlTree{
class avlTreeException{};
public:
class ElementDoesntExist : public avlTreeException{};
class EmptyTree : public avlTreeException{};
class ElementAlreadyExists : public avlTreeException{};
private:
class Node{
friend class avlTree;
ValueType* data;
Node *sonA,*sonB,*dad;
int height,balance;
private:
CompareFunction compare;
int treeSize;
Node* root;
};
(I removed the public\private methods to save space).
For some methods I think I made the right choice: update is a method of Node (updates height,etc).
Insert/remove are functions of the tree.
But for example the function destroyNodeTree(Node*) which is used by the tree destructor. What I did is to have destroyNodeList() call destroyNodeTree(root)
template <class ValueType,class CompareFunction>
void avlTree<ValueType,CompareFunction>::avlTree::destroyNodeTree(Node* rooty) {
if(!rooty){
return;
}
Node *A=rooty->sonA,*B = rooty->sonB;
destroyNodeTree(A);
destroyNodeTree(B);
}
However, I could have made destroyNodeTree() a method of Node, and call it on the root from the destructor (it would be implemented in the same way).
I had a similar issue deciding where the method findNode(const ValueType&) should go, meaning it obviously is a public method of tree, but should I create a method for Node with the same name and have the tree function call the node method on the root? Is it even acceptable to have a public function and an inner class method with the same name?
In my opinion it's better to have it as a method of nodes because that gives more flexibility (I'll be able to search for a node only under a certain node), but on the other hand that means that the method either needs to create an instance of class compare, or have each node keep a copy of an instance, or have class compare as a static function. Each of those has a disadvantage in my opinion though: creating an instance can be costly, keeping a copy can be costly, and forcing the user to make the function static doesn't seem right to me (but I'm horribly inexperienced so fix me if I'm wrong).
In any case I eventually made findNode a treeFunction only and not a method (the HW assignment didn't need the tree to able to search from a specific node so it doesn't make any difference there) but I don't want to write bad code.
To conclude, how do we decide where to save performance,memory,flexibility of the user (would he rather be able to search from any node or create nonstatic compare functions?)

Ramifications of public next pointer in Node class

basic Linked List Data Structure.
class Node {
public:
Node();
Node(int num);
private:
int data_;
Node * next_;
};
class LinkedList {
public:
LinkedList();
void insertAtFront(int toAdd);
void insertAtEnd(int num);
private:
Node * head_;
};
....
void LinkedList::insertAtFront(int toAdd) {
if (head_ == NULL) {
head_ = new Node(toAdd);
}
else {
Node * current = head_;
while (current->next_ != NULL) { //problem in question
}
}
}
This is a rough, far from finished implementation, obviously, so don't judge me on the syntax yet. But I had a question about the obvious warning that my IDE threw at me. Mainly that next_ is private so while loop doesn't work. current->next is inaccessible.
Early in my programming class I had it beaten into me that all class variables should be private/protected always under pretty much all circumstances. Now I can go the obvious route, add a recursive function within the Node class itself that handles the insertion and call it from head_, etc. etc.
OR, and stay with me here, I could just set next_ to public? I really don't see why not. Since main() would only have access to the nodes indirectly through the private head_ pointer, and the actual "data" of the node is private, is there a reason to also keep next_ private?
This advice is still good. You should not expose these fields. Instead, you should either:
Declare "LinkedList" as a friend of "Node"
Move "Node" into "LinkedList"
(Personally I recommend putting "Node" in a "details" or "internal" namespace, adding "LinkedList" as a friend of Node, and creating a "typedef details::Node Node" in the private section of LinkedList unless you intend for other code to use Node, in which case you might also want to consider making public accessor functions that give read only access to the fields -- in that particular case, I would still have a typedef to "Node" within LinkedList though, in that case, I would make the typedef public).
Either of these approaches will grant LinkedList, but just LinkedList, access.
To answer your question regarding the dangers of making it public, some dangers include:
If you change the name or structure of the internal implementation and it is public, you risk breaking external users that have come to rely on these internal implementation details.
You remove the ability to enforce reasonable constraints or be assured of certain assumptions regarding the structure of your data. For example, exposing "next_" would allow a malicious (or incompetent) user of the code to unlink nodes without deleting them or to link nodes circularly in a linked list that was assumed to not be circular. Once you expose internal data members, all bets are off regarding any assumptions that can be made about their structure and values.

OOP: Designing a tree, dividing functionality between Node class and a Tree Class

I need to implement a custom tree class (using C++). Throughout my work I've seen many tree implementations. Some implemented a "super Node" class which was exposed to the user. An instance of which (root node) acted as the tree. Some exposed a tree class, which utilized a node class to construct a tree. Some used the node class as a pure data struct, leaving functionality such as tree construction to the tree class. Others put the construction - like node.Split(), into the node class.
Say you needed to design a binary tree (like a KD-tree). What would be the "best" approach from OOP perspective. Have node class just contain the data, or the logic to split itself into children? How much logic in general should a node class contain?
Thanks ahead for constructive input!
Here's one OOP rule you should always follow,
Every class represents an entity. Classes have properties and methods
i.e. the attributes of the entities and it's behaviour
So you need to follow your understanding of the scenario.
Here's how I look at a node.
It has some data, a right node reference and a left node reference. I don't think a node should be able to do anything except provide you with the data so I would write a node class something like this:
class Node
{
public:
int Data; // yeah, you would obviously use templates, so it's not restricted to a particular type
Node* Left;
Node* Right;
// also you can write constructors and maybe some sort of cast operator overload to be able to make the
// we could also make it return the subtree itself
getRightSubTree(){ return Tree(*Right); }
getLeftSubTree(){ return Tree(*Left); }
};
A Tree should be like this then.
class Tree
{
private:
Node root;
public:
Tree(Node t):root(t){} // every tree should have a root. Cannot be null.
// since the root node will be able to handle the tree structure, now we'll need the necessary methods
void addNode(Node n){
// code here
}
....
getSubTree(int data){
// check if node with that data exists and all
...
Node n = getNode(data);
return Tree(n);
}
};
Okay so I think you've got an idea now. It's all about how you look at the system.

class object also managing a tree structure?

I'm working on a class hierachy, where an object of a class may contain several objects of the same class.
This would lead to a tree structure:
class myClass
{
myClass *parent;
std::vector<std::unique_ptr<myClass> > childs;
/*
* here are some more attributes which describe a myClass object
* but are not related to the tree structure.
* std::string name; for example
*/
public:
//constructors...
//tree management functions
//some more members...
}
However, after thinking about it for a while, i think this is bad practise.
In this approach, myClass not only needs to have members related to its actual behaviour but also for managing the tree, like searching or inserting childs. This would be a lot of different functionality in one single class.
And, as we are lazy programmers, I don't like to re-invent the wheel.
There are some tree-containers out there, for example the well-known "tree.hpp".
Why not using this container for storing the myClass objects?
Well, problem is, some members ob myClass require access to its parents.
Imagine a member-function like getFullName(), which returns not only the "name"-attribute but a complete path to the actual object(all the parent's names). So this function would need to iterate trough all parent nodes until root is reached.
I'm not sure how i can achieve this using tree.hpp or similar containers.
Does myClass then need to store a pointer to the tree-node which contains it?
But I cannot think of an example where an object has information about the container containing it. An object of a class should not know anything of "being contained". Or am I wrong?
Maybe my first approach (myClass does also the tree management) is even OK?
OK, maybe i should ask a simplier question:
What is a good way to let an object know its own position within a container, e.g. a tree?
What is a good way to let an object access its parent in without storing to much (redundant) information in the object itself?
First of all, this is wrong:
class myClass
{
myClass *parent;
std::vector<std::unique_ptr<myClass> > childs;
};
Your children should be stored as a vector of shared_ptr, and the parent should be a weak_ptr.
class myClass
{
std::sweak_ptr<myClass> parent;
std::vector<std::shared_ptr<myClass> > children;
};
However, it looks like what you want is a template tree container. So your class should look like this:
class myClass
{
/*
* here are some more attributes which describe a myClass object
* but are not related to the tree structure.
* std::string name; for example
*/
public:
//constructors...
//tree management functions
//some more members...
};
And the tree container should be something like this (conceptually):
template <typename T>
class tree
{
std::sweak_ptr<tree> parent;
std::vector<std::shared_ptr<tree> > children;
T value;
};
This tree can be generic and hold different types of objects, including myClass.

Structuring C++ class hierarchies for maintainability and encapsulation

I have some general questions about encapsulation as it relates to maintainability. Here is an example class that I used to assist in the construction of a parse tree. (I have avoided STL for education's sake.)
The Node class describes a node in a tree. The managing class ParseTree (not shown) is responsible for building and maintaining the collection of Node objects in a meaningful, tree-like way.
// contents of node.h, not including header guard or namespace
class Token;
class Node {
public:
static const Node* FindParent(const Node* p_root, const Node* p_node);
static int Height(const Node* p_root);
static void Print(const Node* p_root);
Node(const Token * p_tok=0) : p_left_(0), p_right_(0), p_tok_(p_tok) {}
~Node() { delete p_left_; delete p_right_; }
const Node* p_left(void) const { return p_left_; }
const Node* p_right(void) const { return p_right_; }
const Token* p_tok(void) const { return p_tok_; }
private:
friend class ParseTree;
Node* p_left_;
Node* p_right_;
Token* p_tok_;
};
The following four topics relate to encapsulation.
The static methods in the Node class are declared static because they can be phrased without using any private members. I'm wondering if they should live outside Node in a common namespace, or maybe as static members within ParseTree. Should my decision be dominated by the fact that ParseTree is responsible for trees, and by that logic the functions should live in ParseTree?
On a related note, the reason the static methods are in Node instead of ParseTree was because ParseTree was filling up with lots of members. I've read that keeping class small and agile is better for maintainability. Should I be going out of my way to find methods that don't rely on private member access and pull them out of my class definition and put them into functions grouped within the same namespace as the class?
I had also read some advice about avoiding mutators on private members since it tends to break encapsulation, so I ended up only having accessors, and let ParseTree handle any modifications using its friendship with Node. Is this really better than having mutators and just ending the friendship with ParseTree? If I add mutators, then Node can be reused in other contexts without adding another friendship.
If I add mutators and remove the static functions from Node, I feel like I could just make the data members public and remove all the accessors/mutators/friend declarations. I have the impression that such an approach would be bad form. Should I be skeptical of my design if I have accessor/mutator pairs for each private member?
If there's anything else obvious and wrong about my approach that I didn't think to ask, I'd appreciate hearing about it.
Ask yourself, what's a Node? Clearly, it's something that may have a parent, a left child and a right child. It also holds a pointer to some data. Does a node have a height? It depends on the context, is it possible that your nodes may at some point be part of a cycle? A ParseTree has a concept of height, it doesn't seem a node does.
To be honest, I suggest you get your program logic correct first, and then you can worry about the OO bells and whistles.
The questions you're asking will probably answer themselves as you proceed.
I think Node is a bit too crowded with these accessors, which are apparently just an indirect way of exposing your private members. I think removing these static members to an application namespace would be a bit cleaner. Eg:
namespace mycompiler {
class Node {
...
};
class ParseTree {
...
};
const Node* FindParent(...);
int Height(...);
void Print(...);
}
In that way you could still avoid polluting the global namespace, but at the same time keeping your Node and ParseTree classes smaller. You could also overload some mycompiler:: functions (e.g. Print()) to accept any object from your namespace if you don't want to stick them into your classes. This would make Node and ParseTree more intelligent containers, while some external logic (to the relevant classes) could be isolated in mycompiler::.