Have I to call delete in this classes' destructors?
2 pointers to Node:
class Node {
private:
char Ch;
int Key;
Node* L;
Node* R;
public:
Node() { L = NULL; R = NULL; }
Node(char, int, Node*, Node*);
~Node();
};
Vector of pointers to Node:
class Example {
private:
vector<Node*> A;
public:
Node() {}
Node(vector<Node*>);
~Node();
};
In another class of my project I allocate Nodes through "new"!
If you allocate the nodes using new then you will eventually need to delete them, e.g. vector does not delete them for you, it only clears up the vector itself but not what the elements point to (since you have a vector of pointers). As you can tell the ownership of a node can be a bit tricky to establish in your classes - what class should delete? That is why using smart pointers like shared_ptr<> and unique_ptr<> make your life much easier.
e.g.
std::shared_ptr<Node> L;
std::shared_ptr<Node> R;
and
std::vector<std::shared_ptr<Node>> A;
then you do not need to worry about deleting
Related
In c++ liked list Why we have to write node pointer like node* without specifying int, double etc. and we can also declare new node pointers in main without using any node class declaration.
class Node {
public:
int data;
Node* next;
};
If its any different kind of pointer then what it is called?
In your code
class Node {
public:
int data;
Node* next;
};
there is only one kind of node, and it has an int for data. That is why you don't need to write Node<int> or Node<double>. But you could change your code
template <typename T>
class Node {
public:
T data;
Node<T>* next;
};
This is called a template, and instead of only having an int for the data you can have any type. But now you have to say what that type is when you declare a variable. E.g.
Node<double>* ptr = new Node<double>();
I have an array of pointers to an object. The object itself has a pointer member.
When I write a destructor the array of pointers does it also destruct the member pointer?
Is it safe to loop through a range for loop in destructor as objects getting deleted instead of an old style for loop?
Heres the class with array of pointer to objects.
class Graph {
EdgeNode* edges[MAX_VERTICES] = { nullptr };
public:
Graph() {};
~Graph() {
for (EdgeNode* edge : edges) { //Is it safe to loop like this versus a foor loop as objects getting deleted?
delete edge;//Does it also delete the edge->next ???
}
}
};
Heres the class whose array is maintained in the Graph class above
#include <iostream>
const int MAX_VERTICES = 1000;
class EdgeNode { //Do I need a destructor here to ensure the next is getting deleted?
EdgeNode* next{ nullptr };
public:
EdgeNode() : next(nullptr) {}
EdgeNode(EdgeNode* _next) : next(_next) {}
EdgeNode* getNext() const { return next; };
};
So I have a parent Class which is:
class Node
{
public:
Node();
void setParentNode(Node* parent) {this->parentNode = parent;}
Node* getParentNode() {return this->parentNode;}
std::vector<Node> getChildNodes(){return this->childNodes;}
void addChildNode(Node* node);
void removeNode();
private:
std::vector<Node*> childNodes;
Node* parentNode = nullptr;
};
And a child inheriting from that class:
class Cube : public Node
{
public:
Cube();
};
Now I have another file which has a function that uses the child class:
#include "cube.h"
void addCubes(){
Cube mainCube;
for(int i = 0; i < 10; i++){
Cube c;
mainCube.addChildNode(c);
}
}
Problem is that mainCube doesn't see the addChildNode function which the parent has. What is the point of inheriting from another class if the parents functions aren't accessible from another place using the child class?
No, the parent classes public functions are callable from the child object.
However, the prototype of the function is
void Node::addChildNode(Node node);
So it's taking a Node object & not a Cube object.
So your compiler cannot find a function which takes a Cube object & hence the error.
The fix is to use a pointer to Node or reference to Node while declaring/defining the function.
So you function should be
void addChildNode(Node & node);
In which case, the Node object can be passed to the function & the compiler will find it.
Even better would be to have
// if you aren't looking to modify the passed object inside addChildNode
void addChildNode(const Node & node);
The following is fine & hence the function will work
Cube b;
Node &a = b;
or
Node * pn = &b;
The derived classes should be able to see the addChildNode function if you keep the signature of the function aligns. This is not a big issue. However, there are a few more "serious" issues with your code:
You need to make the base class' destructor virtual to avoid some undefined behaviors.
You have to design the ownership of nodes carefully. I guess you want the Node class to own and manage its children nodes. That means function addChildNode actually takes the ownership of the passed in node object, and it should also be deleted during destruction.
In function addCubes(), there is a loop that keeps calling addChildNode function but passes the local variable Cube c; which will be out of scope and destroyed after the loop. Thus, the parent object mainCube will holds pointers to already destroyed objects, and it will cause a crash.
After fixing all these issues, your code looks like this:
class Node
{
public:
Node() {};
virtual ~Node() {
for(auto n: childNodes) delete n;
};
void setParentNode(Node* parent) {this->parentNode = parent;}
Node* getParentNode() {return this->parentNode;}
std::vector<Node*> getChildNodes(){return this->childNodes;}
void addChildNode(Node* node) {
childNodes.push_back(node);
};
void removeNode();
private:
std::vector<Node*> childNodes;
Node* parentNode = nullptr;
};
class Cube : public Node
{
public:
Cube() {};
};
void addCubes(){
Cube mainCube;
for(int i = 0; i < 10; i++){
Cube *c = new Cube();
mainCube.addChildNode(c);
}
}
It is preferred to use smart pointers to manage memory, and the code is more elegant and easier to read, and it makes it harder to make mistakes :-).
#include <memory>
class Node
{
public:
Node() {};
virtual ~Node() {};
void setParentNode(Node* parent) {this->parentNode = parent;}
Node* getParentNode() {return this->parentNode;}
std::vector<std::shared_ptr<Node>>& getChildNodes(){return this->childNodes;}
void addChildNode(std::shared_ptr<Node> node) {
childNodes.push_back(std::move(node));
};
void removeNode();
private:
// childNodes own elements in it, they will be deleted automatically.
std::vector<std::shared_ptr<Node>> childNodes;
Node* parentNode = nullptr;
};
class Cube: public Node
{
public:
Cube() {};
};
void addCubes(){
Cube mainCube;
for(int i = 0; i < 10; i++){
auto c = std::make_unique<Cube>();
mainCube.addChildNode(std::move(c));
}
}
Assuming that you have shared the entire implementation of your code. You have not defined the body of the function addChildNode, similar to setParentNode etc. You need to do something like childNodes.push_back(node); inside that function.
Note: It is also necessary that you pass the input to addChildNode as shown in the answer by #user93353. Also, define childNodes as std::vector<Node *> in order to avoid object slicing.
I am trying to build a node class for binary tree implementation. Here is the header file for Node class:
class Node {
public:
Node();
Node(int value);
void setParent(Node& parent);
void setLeftChild(Node& child);
void setRightChild(Node& child);
void setValue(int value);
void setIndex(int index);
void setHeight(int height);
private:
int value;
Node& parent;
Node& leftChild;
Node& rightChild;
int height;
int index;
};
Now, I want to write the constructor Node(int value) declared above.
How shall I initialize the leftChild, rightChild, parent fields? They are also Node(s), so I want to call default constructor on them but it does not seem to work.
Node::Node(int value) : value(value), parent(), leftChild(), rightChild(){
}
Compiler is saying that "reference to type 'Node' needs an initializer"
Thanks.
You should use a constructor which specify the parent of the node:
Node(Node *parent, int value);
When you create the root node you simply call this contructor with NULL as parameter.
All the reference to parent and childs should be pointers.
In this case it makes sense to use pointers over references and initialize them to NULL. By doing this you may also check if a node has a child or parent (i.e. is not root node) by checking for a NULL pointer. Also, be sure to add a destructor to deallocate memory.
You could better use pointers (Node*) instead of references (Node&). And in constructor just assign nullptr to them.
References are neccessary to reference some object (and obviously when you don't have a left or right child you can't reference them). So pointers come here to help you - they allow point to nothing - in this case nullptr is used as nothing.
I'm interested in doing something like the following to adhere to a Null Object design pattern and to avoid prolific NULL tests:
class Node;
Node* NullNode;
class Node {
public:
Node(Node *l=NullNode, Node *r=NullNode) : left(l), right(r) {};
private:
Node *left, *right;
};
NullNode = new Node();
Of course, as written, NullNode has different memory locations before and after the Node class declaration. You could do this without the forward declaration, if you didn't want to have default arguments (i.e., remove Node *r=NullNode).
Another option would use some inheritence: make a parent class (Node) with two children (NullNode and FullNode). Then the node example above would be the code for FullNode and the NullNode in the code above would be of type NullNode inheriting from Node. I hate solving simple problems by appeals to inheritence.
So, the question is: how do you apply Null Object patterns to recursive data structures (classes) with default arguments (which are instances of that same class!) in C++?
Use extern:
extern Node* NullNode;
...
Node* NullNode = new Node();
Better yet, make it a static member:
class Node {
public:
static Node* Null;
Node(Node *l=Null, Node *r=Null) : left(l), right(r) {};
private:
Node *left, *right;
};
Node* Node::Null = new Node();
That said, in both existing code, and amendments above, you leak an instance of Node. You could use auto_ptr, but that would be dangerous because of uncertain order of destruction of globals and statics (a destructor of some global may need Node::Null, and it may or may not be already gone by then).
I've actually implemented a recursive tree (for JSON, etc.) doing something like this. Basically, your base class becomes the "NULL" implementation, and its interface is the union of all interfaces for the derived. You then have derived classes that implement the pieces- "DataNode" implements data getters and setters, etc.
That way, you can program to the base class interface and save yourself A LOT of pain. You set up the base implementation to do all the boilerplate logic for you, e.g.
class Node {
public:
Node() {}
virtual ~Node() {}
virtual string OutputAsINI() const { return ""; }
};
class DataNode {
private:
string myName;
string myData;
public:
DataNode(const string& name, const string& val);
~DataNode() {}
string OutputAsINI() const { string out = myName + " = " + myData; return out; }
};
This way I don't have to test anything- I just blindly call "OutputAsINI()". Similar logic for your whole interface will make most of the null tests go away.
Invert the hierarchy. Put the null node at the base:
class Node {
public:
Node() {}
virtual void visit() const {}
};
Then specialize as needed:
template<typename T>
class DataNode : public Node {
public:
DataNode(T x, const Node* l=&Null, const Node* r=&Null)
: left(l), right(r), data(x) {}
virtual void visit() const {
left->visit();
std::cout << data << std::endl;
right->visit();
}
private:
const Node *left, *right;
T data;
static const Node Null;
};
template<typename T>
const Node DataNode<T>::Null = Node();
Sample usage:
int main()
{
DataNode<char> a('A', new DataNode<char>('B'),
new DataNode<char>('C'));
a.visit();
return 0;
}
Output:
$ ./node
B
A
C