c++ declaring a variable of a class within that class - c++

I have the following code:
template <typename T>
class Node{
public:
Node<T>(T data){
this->data = data;
}
T data;
Node<T> left;
Node<T> right;
};
But it doesn't like how I have member variables of the same type as the class they are in because the compiler doesn't know what "Node" is.

You want to declare left and right as Node<T> *:
Node<T> *left;
Node<T> *right;
The problem is not just that the compiler doesn't have the complete definition yet, but that you are trying to say a Node contains two other Nodes, so there is no sensible definition for the size of a Node.

Create a forwarding class declaration:
template<typename T>
class Node;
template<typename T>
class Node {
public:
T data;
Node<T> left, right;
// implementation here
}

This ---> Node<T> left,right causes compiler error. To fix it, you can declare left and right to be pointers, references, or static nodes:
template<typename T>
class Node {
public:
Node(T data) : data(data){}
T data;
Node<T> *left, *right; // Ok
/* OR */
Node<T> &left, &right; // Ok
/* OR */
static Node<T> left, Node<T> right; // also Ok
Node<T> left, right; // No way, causes error
};

Related

Cannot implement array initialization in TreeNode Template C++ Scapegoat Tree

I get an initialization error for a TreeNode class constructor… This is the function:
TreeNode* a = new TreeNodens; Is the issue here, not sure what I have to add to TreeNode but it needs some type of tweak!
template <typename T>
void ScapegoatST<T>::rebuild(TreeNode<T>* node){
int ns = getHeight(node);
TreeNode<T>* p = node->getParent();
TreeNode<T>* a = new TreeNode<T>[ns]();
TreeNode<T>* r;
packintoArray(node,a,0);
if (p == NULL){
r = buildBalanced(a,0,ns);
r->setParent(NULL);
} else if (p->getRight() == node){
TreeNode<T>* Tr = buildBalanced(a, 0, ns);
p->setRight(Tr);
p->getRight()->setParent(p);
} else {
p->setLeft(buildBalanced(a,0,ns));
p->getLeft()->setParent(p);
}
}
Here is the TreeNode.h:
#ifndef TREE_NODE_H
#define TREE_NODE_H
#include <cstdlib>
#include <iostream>
using namespace std;
template <typename T>
class TreeNode{
public:
TreeNode(T nData);
virtual ~TreeNode();
T getData();
TreeNode<T>* getLeft();
TreeNode<T>* getRight();
TreeNode<T>* getParent();
void setData(T nData);
void setLeft(TreeNode<T>* nleft){left=nleft;};
void setRight(TreeNode<T>* nright){right=nright;};
void setParent(TreeNode<T>* nparent){parent=nparent;};
template <typename S>
friend class ScapegoatST;
private:
T data;
TreeNode<T>* left;
TreeNode<T>* right;
TreeNode<T>* parent;
};
template <typename T>
TreeNode<T>::TreeNode(T nData){
data = nData;
left = NULL;
right = NULL;
}
template <typename T>
TreeNode<T>::~TreeNode(){
delete left;
delete right;
delete parent;
data = NULL;
}
template <typename T>
T TreeNode<T>::getData(){
return data;
}
template <typename T>
void TreeNode<T>::setData(T nData){
data = nData;
}
#endif
I tired creating a constructor for the array initialization but it wasn’t successful.
The issue here is that you've created the constructor TreeNode(T nData), which prevents the constructor with no arguments TreeNode() from being generated, but you call that constructor when you do new TreeNode<T>[ns]().
One solution would be to add a constructor TreeNode(), with a body like so:
template<typename T>
TreeNode<T>::TreeNode() {
left = NULL;
right = NULL;
}
This will mean that constructing a TreeNode with no nData will result in the node's data field being default-initialized (for primitive types, it will contain an undefined value, and for classes it will act like T() was called to construct the data value).

Defining a struct within a class (doubly linked list) using a template

I have implemented each of the methods for this class but I am struggling with this last error. I was given instructions to define the Node struct within the private section of the class linkedlist. I get errors such as:
"error: Node is not a class template"
and
"error: non-template type 'Node' used as a template"
My code works if I rearrange things and place the Node struct outside of the class altogether, but that is not really the solution I am looking for.
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
typedef int element_type;
template<class element_type>
class linkedlist
{
private:
struct Node<element_type>{
Node<element_type>* next;
Node<element_type>* prev;
element_type data;
};
Node<element_type>* head;
Node<element_type>* tail;
unsigned int size;
public:
linkedlist();
~linkedlist();
void push_back(const element_type& z);
void push_front(const element_type& z); //add front
void print() const;
// will initialize list with n nodes
explicit linkedlist(unsigned int n);
};
The TL;DR version is to drop the template syntax on Node:
struct Node{
Node* next;
Node* prev;
element_type data;
};
Node* head;
Node* tail;
Because Node is defined inside the class template, it can already access the type element_type. The compiler error is just telling you that you can't use template syntax when declaring a structure which is not itself a template.
Just remove template parameter from struct Node.
struct Node {
Node * next;
Node * prev;
element_type data;
};
Node * head;
Node * tail;
unsigned int size;

C++ Binary Tree, modifying root node, pointer to pointer to root node

I realize the title isn't too descriptive so here are the details. I'm implementing my own Binary Tree class in C++. I have written a template Node class and template Binary Tree class already, for the most part, and am stuck on something. I created an empty binary tree (root node is null) and when I try to set that node it fails miserably. here is the code and more explanation:
template<class T> class Node
{
T _key;
Node<T> *_leftChild;
Node<T> *_rightChild;
public:
Node();
Node(T key);
Node(T key, Node<T> *leftChild, Node<T> *rightChild);
~Node();
bool hasLeftChild();
bool hasRightChild();
void setKey(T key);
void setLeftChild(Node<T> *node);
void setRightChild(Node<T> *node);
T getKey();
Node<T>* getLeftChild();
Node<T>* getRightChild();
bool compare(Node<T> *compareNode); // return true if this.Node < compareNode
};
Node implementation not really necessary.. ( I dont think ) it's quite long.
#include "Node.cpp"
#include <iostream>
using namespace std;
template<class T> class BinaryTree
{
Node<T> *_root;
public:
BinaryTree();
BinaryTree(Node<T> *root);
~BinaryTree();
Node<T>* getRoot();
void insert(Node<T> **root, Node<T> *node);
};
template<class T>
BinaryTree<T>::BinaryTree()
{
this->_root = NULL;
}
template<class T>
BinaryTree<T>::BinaryTree(Node<T> *root)
{
this->_root = root;
}
template<class T>
BinaryTree<T>::~BinaryTree()
{
// delete stuff
}
template<class T>
Node<T>* BinaryTree<T>::getRoot()
{
return this->_root;
}
template<class T>
void BinaryTree<T>::insert(Node<T> **root, Node<T> *node)
{
if(!*root)
{
*root = node;
}
}
Main:
BinaryTree<int> *tree = new BinaryTree<int>();
Node<int> *root = tree->getRoot();
Node<int> **root1 = &root;
cout << tree->getRoot() << endl;
Node<int> *noChildrenNode = new Node<int>(2);
tree->insert(&root1, noChildrenNode);
cout << tree->getRoot() << endl;
Inserts current functionality is just supposed to replace the NULL root pointer to the node pointer passed in as a parameter. The failing miserably part is since the pointer is a copy it isn't actually setting the root node.. but I can't seem to figure out how to set up a pointer to a pointer to the root node so it can be altered.. I've got to be close and any help will be MUCH appreciated.
Thanks
First, you've got to include the exact text of any error messages. "fails miserably" is not adequate.
I think you want
root = node;
Not
*root = node;
Because if root is null, using *root is a null pointer exception.

error: request for member `member` in `cur`, which is of non-class type node<int>* Binary Tree

I have a binary tree
template<class item_type>
struct node{
item_type x;
node<item_type> *left;
node<item_type> *right;
};
template<class item_type, class param>
class Tree{
node<item_type> *root;
public:
//functions
In some of the functions I use
node<item_type> *cur = root;
and traverses through the tree via cur->left or cur->right
this incurs me the error:
error: request for member Get_Height /a function in cur/, which is of non-class type node* Binary Tree
template<class item_type, class param>
int Tree<item_type, param>::Get_Height()
{
node<item_type> *cur = root;
while(cur->left!=NULL || cur->right!=NULL)
{
if(cur==NULL)
return 0;
return max(cur->left.Get_Height(), cur->right.Get_Height())+1;
}
}
I'm pretty sure left is of type node
According to the error, the function seems to take a pointer to a node, instead of the actual tree so, that shouldn't be an issue.
cur is of type struct node *, which is a pointer.
so I suspect, it should be cur->left != NULL and also, left is a pointer as well, so it should be
return max(cur->left->Get_Height(), cur->right->Get_Height())+1;
There is something majorly wrong in your code, there is no Get_Height() member in the struct node.

Node implementation Binary Tree

I have the following implementation for the node class:
template<class T> class binTree; // forward declaration
template<class T> class Node {
friend class binTree<T>; // class binTree is friend
public:
//default constructor
Node(const T& d = T(), Node<T> *l = NULL, Node<T> *r = NULL) : data(d),
left(l), right(r) {};
private:
T data;
Node<T> *left, *right;
};
I'm trying to define a new node a the root of my tree, but I keep getting compilation errors...
template<class T>
void binTree<T>::insert(Node<T>*& n, const T& d){
if(n == NULL)
root = Node<T>(d);
}
I'm confused by the const T& d = T() parameter.
I think you just need to declare the binTree class and its members before you try to define the member. The following code compiles for me:
#include <cstdlib>
template<class T> class binTree; // forward declaration
template<class T> class Node {
friend class binTree<T>; // class binTree is friend
public:
//default constructor
Node(const T& d = T(), Node<T> *l = NULL, Node<T> *r = NULL) : data(d),
left(l), right(r) {};
private:
T data;
Node<T> *left, *right;
};
template <class T> class binTree
{
public:
binTree() { }
void insert(Node<T>*& n, const T& d);
private:
Node<T> root;
};
template<class T>
void binTree<T>::insert(Node<T>*& n, const T& d){
if(n == NULL)
root = Node<T>(d);
}
int main(int argc, char **argv)
{
Node<int>* nt;
binTree<int> btree;
btree.insert(nt, 4);
}
Having said this, your concept of the data structure seems messed up. Why does the insert routine in binTree require a node argument?
I'm not quite sure why you have that default override for the d variable in your default constructor. In my implementation of a Node for my Tree class, I had no default assignment. I think the issue is T(). I would recommend not trying to do that default assignment in the params listing, but instead do it in the BMI List. So it would look kind of like "data(new T), left(NULL), right(NULL)"
Additionally I would say I'm not quite certain as to why you are using T(). If that doesn't work, please post the error code so that we can have a better understanding of what is going on.