I have 2 files: Node.h, Node.cpp,
In Node.h, I create the prototype for the Node class. In the prototype I create a string array 'name'. In the Node.cpp class, I tried to use a function that gives 'name' a value, but i keep getting undeclared identifier even though i identified 'name' in Node.h
node.h
#include "iostream"
#include "string.h"
#include "stdafx.h"
#include "stdio.h"
template<class T>
class Node{
char name[256];
bool useable;
public:
//Constructors
Node();
Node(const T& item, Node<T>* ptrnext = NULL);
T data;
//Access to next Node
Node<T>* nextNode();
//List modification
void insertAfter(Node<T>* p);
Node<T>* deleteAfter();
Node<T>* getNode(const T& item, Node<T>* nextptr = NULL);
//Data Retrieval
char *getName();
void *setName(char[]);
bool isUsable();
};
node.cpp
#include "Node.h"
//Default Constructor
template<class T>
Node<T>::Node(){
}
//This constructor sets the next pointer of a node and the data contained in that node
template<class T>
Node<T>::Node(const T& item,Node<T>* ptrnext){
this->data = item;
this->next = ptrnext;
}
//This method inserts a node after the current node
template<class T>
void Node<T>::insertAfter(Node<T> *p){
//Links the rest of list to the Node<T>* p
p->next = this->next;
//Links the previous node to this one
this-> next = p;
}
//This method deletes the current node from the list then returns it.
template<class T>
Node<T> * Node<T>::deleteAfter(){
Node<T>* temp = next;
if(next !=NULL){
next = next->next;
}
return temp;
}
template<class T>
Node<T> * getNode(const T& item, Node<T>* nextptr = NULL){
Node<T>* newnode; //Local pointer for new node
newNode = new Node<T>(item,nextptr);
if (newNode == NULL){
printf("Error Allocating Memory");
exit(1);
}
return newNode;
}
void setName(char input[256]){
strncpy(name,input,sizeof(name));
}
I see three things immediately wrong with the following code.
void setName(char input[256]){
strncpy(name,input,sizeof(name));
}
You did not provide the class name. This is therefore declaring a static function, and not a class member. You also forgot to do this on your getNode function.
You left out the template statement.
You put a template implementation in a cpp file. Be aware that you cannot compile the cpp file as an object -- it must be included in a header, or you can ditch the file altogether and move your implementation into your header.
Related
I'm trying to implement my own Stack in C++ but I keep getting this error when I try to use the method pop() in which what I'm trying to do is:
Save element from the top in a variable called "res".
Get the reference to the next element from the node class and set it as the top.
size--
Return the variable "res".
If you could help me I'd appreciate it. Thank you!
Node class:
template<class T>
class Node {
private:
Node<T>* next;
T element;
public:
Node();
Node(const Node& orig);
~Node();
void setElement(T el);
T getElement();
Node<T>* getNext();
void setNext(Node<T>* ne);
};
Stack class:
#include "EmptyStackException.cpp"
#include "Node.cpp"
#include <iostream>
using namespace std;
template<class T>
class LinkedStack {
private:
int siz;
Node<T>* first;
public:
LinkedStack();
~LinkedStack();
int size();
bool isEmpty();
void push(T e);
T top();
T pop();
};
template<class T>
void LinkedStack<T>::push(T e) {
Node<T> node = Node<T>();
node.setNext(first);
node.setElement(e);
first = &node;
siz++;
}
template<class T>
T LinkedStack<T>::pop() {
T res = first->getElement();
first = *(first->getNext());
siz--;
}
template<class T>
void LinkedStack<T>::push(T e) {
Node<T> node = Node<T>();
node.setNext(first);
node.setElement(e);
first = &node;
siz++;
}
Since node is an object that is local to this function, as soon as this function ends, it is destroyed. However, first contains a pointer to it. So when this function returns, first contains a pointer to an object that no longer exists. You probably want this:
template<class T>
void LinkedStack<T>::push(T e) {
Node<T>* node = new Node<T>();
node->setNext(first);
node->setElement(e);
first = node;
siz++;
}
Now, node still ceases to exist when this function returns. But first doesn't contain a pointer to node, it contains the value of node -- a pointer to a dynamically allocated object.
Note that you will have to manage the lifetime of that object somehow. Ideally, you wouldn't use raw pointers so that you don't have that burden.
#ifndef __linkedListH__
#define __linkedListH__
template<class T>
class Node
{
public:
T data;
Node *next;
};
template<class T>
class linkedList
{
public:
Node<T> *head;
linkedList();
Node<T>* returnHead();
Node<T>* Insert(Node *head,T data);
};
template<class T>
linkedList<T>::linkedList()
{
head = NULL;
}
Node* linkedList<T>::returnHead()
{
return head;
}
Node* linledList<T>::Insert(Node *head,int data)
{
Node *newNode = new Node();
newNode->data = data;
newNode->next = NULL;
if(!head)
return newNode;
Node *temp = head;
while(temp->next)
{temp=temp->next;}
temp->next = newNode;
return head;
}
#endif
In this implementation of a linked list, Pls help me with the declaration of "returnHead" and "Insert" method. When I call these methods from main function, I'm getting the following errors with declaration of both methods:
1.ISO C++ forbids declaration of 'Node' with no type
2.expected ';' before '*' token
You're missing a few template <class T> and <T> components:
template <class T>
Node<T>* linkedList<T>::returnHead()
{
return head;
}
template <class T>
Node<T>* linledList<T>::Insert(Node<T> *head,int data)
{
Node<T> *newNode = new Node<T>();
newNode->data = data;
newNode->next = NULL;
if(!head)
return newNode;
Node<T> *temp = head;
while(temp->next)
{temp=temp->next;}
temp->next = newNode;
return head;
}
This need to repeat the template declaration header before each member function is one of the reasons why member functions of class templates are often implemented inline in the class right where they're declared.
Also, I believe the parameter data should be of type T, and not int. It doesn't make much sense otherwise.
As an additional note, you might want to give your Node class template a constructor (taking next and data), so that you don't have to initialise it from outside.
Unrelated issue: names which contain two consecutive underscores (or ones which start with an underscore followed by an uppercase letter) are reserved for the compiler & standard library; using them for your own things is illegal. Rename the include guard suitably.
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.
Suppose I have the following definition of List and Node:
template <class T>
class List {
public:
class Iterator;
class ConstIterator;
//Constructors and Destructors.
List() : head(NULL), tail(NULL), size(0) {}
List(const List& list);
~List();
//Methods
Iterator begin();
ConstIterator begin() const;
Iterator end();
ConstIterator end() const;
void insert(const T& data);
void insert(const T& data, const Iterator& iterator);
void remove(const Iterator& iterator);
int getSize() const;
Iterator find(const T& item);
ConstIterator find(const T& item) const;
void sort();
//Operators
List operator = (const List& list);
private:
class Node;
Node* head;
Node* tail;
int size;
};
template <class T>
class List<T>::Node
{
public:
//Constructors and destructors
Node(const T& _data, const Node* _next) : data(_data), next(_next) {}
~Node(); //Destructor
//Methods
//Operators
Node operator = (const Node& node);
private:
T data;
Node* next;
};
I'm writing a function to insert data into a list like this:
template<class T>
void List<T>::insert(const T& data)
{
Node newNode = new Node(data, NULL);
if (head == NULL)
{
head = &newNode;
tail = &newNode;
}
else
{
(*tail)->next = &newNode;
tail = &newNode;
}
size++;
}
However what I find strange is that if I swap (*tail)->next = &newNode; to (*tail).next = &newNode; it still compiles. Why, and what is the correct way of doing it?
The definitions of your classes can be (for the purposes of this question) simplified into:
class List {
...
private:
Node* head;
Node* tail;
};
class Node {
...
private:
Node* next;
};
Now in your List::insert method:
Node newNode = new Node(data, NULL);
(*tail)->next = &newNode;
...when you use new expression, the result will be pointer to the newly allocated memory.
What you should do is:
Node* newNode = new Node(data, NULL);
tail->next = newNode; // <-- equivalent to (*tail).next = newNode;
Using Node->tail is short form of writing (*Node).tail. Both forms are valid. Strangeus is the fact that you say that (*Node)->tail compiles. To this happens, Node must be defined as a double pointer, i.e.:
Node **tail;
But your code has some others bugs in. In this line:
Node newNode = new Node(data, NULL);
you are define a local object and assing a dynamic memory to it. The correct way is:
Node *newNode = new Node(data, NULL); // defining it as a pointer
and instead of assing as:
head = &newNode;
do:
head = newNode;
As a final note, consider using smart pointer instead of raw pointer. The former is safer than the last
The -> operator will automatically derefference a pointer for you then call the method to the right. So:
tail->next
would also work but
tail.next
wouldn't because tail is a pointer. To use the . operator you have to defrence the pointer first as in
(*tail).next
(*tail)
turns your pointer into an object. At that point you can use either -> or .
A . will not work on a pointer but -> will.
Generally, just for easy of typing I use -> because it is shorter then using (*) to turn a pointer into an object just so I can use a dot but they are equivalent operations.
You have noticed that (*tail)->next = &newNode and (*tail).next = &newNode both compile, which strikes you as odd.
But somehow you might also have noticed that this line also compiles!
Node newNode = new Node(data, NULL);
That is the thing that you should give you pause.
You are inside of a template here. Lots of things "compile".
Did you try instantiating the template?
ADDENDUM:
Here just to show you how crazy things can be, check out this program:
#include <iostream>
using namespace std;
template <class T>
class C {
void f();
};
template <class T>
void C<T>::f() {
int x = new int;
}
int main() {
std::cout << "Hello, world\n";
}
Now check this out:
$ g++ template-example.cpp && ./a.out
Hello, world
But now notice
#include <iostream>
using namespace std;
int main() {
int x = new int;
std::cout << "Hello, world\n";
}
which yields:
$ g++ hello.cpp
hello.cpp: In function ‘int main()’:
hello.cpp:4: error: invalid conversion from ‘int*’ to ‘int’
TL;DR: WHEN YOU ARE IN A TEMPLATE, THINGS THAT SHOULD NOT COMPILE SOMETIMES "DO"! (They're not really compiling -- YET!)
This code is not compiling in my system; I'm using Eclipse.
// Linked list head
template<class T>
struct Node
{
// constructor
Node(const T& a) : pNext(NULL), data(a) {}
Node* pNext; //link
T data;
}; // end of header
// List code
#include <iostream>
#include "LinkedList.h"
template<class T>
class linkedList
{
public:
typedef Node<T> Node;
//constructor creates empty list
linkedList() : pHead(NULL), size(0) {}
~linkedList()
{
Node* pIter = pHead;
while(pIter != NULL)
{
Node* pNext = pIter->pNext;
delete pIter;
pIter = pNext;
}
}
void insert(const T& data)
{
Node* pInsert = new Node(data);
if(pHead == NULL)
{
pHead = pInsert;
}
else
{
pInsert->pNext = pHead;
pHead = pInsert;
}
}
private:
Node* pHead; // always points to head of list
unsigned int size; // stores number of elements in list
};
Here is the error message:
./LinkedList.cpp:14:18: error: declaration of 'typedef struct Node<T> linkedList<T>::Node'
../LinkedList.h:4:1: error: changes meaning of 'Node' from 'struct Node<T>'
make: *** [LinkedList.o] Error 1
The error is fairly clear: Don't reuse the name Node. Instead you can write something like this:
typedef Node<T> node_type;
Template names and type names share the same namespace in C++, so you cannot use the same name for two distinct entities, even though one is a template and the other a type.
(Somewhat tangentially, there is a fair amount of subtlety surrounding tag names both in C and C++; this article may be worth a read, and this and this.)