Class Templates - Undefined reference to my Node class' deconstructor. - c++

I am implementing an Ordered List data structure in C++ using class templates.For simplicity, I implemented each constructor and function inline. I made my own Node class for this project.
The compiler error is pasted at the bottom of this question. "undefined reference to `Node::~Node()'". This is my first time working with templates and I've never seen this error before. I have no idea where to begin.
Any help would be appreciated!
Node.h
#ifndef NODE_H
#define NODE_H
#include <iostream>
#include <cstdlib>
template <class E>
class Node {
public:
Node(const E init_data = NULL, Node<E>* init_link = NULL){data = init_data; link = init_link;}
Node(const Node<E>& orig){data = orig.getData(); setLink = NULL;}
virtual ~Node();
E getData() const{return data;}
void setData(E newData){data = newData;}
Node<E>* getLink(){return link;}
void setLink(Node<E>* nextLink) {link = nextLink;}
private:
E data;
Node<E>* link;
};
#endif /* NODE_H */
MyOrderedList.h
#ifndef MYORDEREDLIST_H
#define MYORDEREDLIST_H
#include <iostream>
#include <cstdlib>
#include "Node.h"
template <class E>
class MyOrderedList;
template <class E>
std::ostream& operator <<(std::ostream& out, const MyOrderedList<E>& list);
template <class E>
class MyOrderedList {
public:
MyOrderedList()
{/*IMPLEMENTATION*/}
MyOrderedList(const MyOrderedList<E>& orig)
{/*IMPLEMENTATION*/}
void operator =(const MyOrderedList<E>& orig)
{/*IMPLEMENTATION*/}
virtual ~MyOrderedList()
{/*IMPLEMENTATION*/}
bool remove(E data)
{/*IMPLEMENTATION*/}
MyOrderedList<E> kLargest(int k) const
{/*IMPLEMENTATION*/}
E get(int pos) const
{/*IMPLEMENTATION*/}
void insert(E data)
{/*IMPLEMENTATION*/}
MyOrderedList<E> operator +(const MyOrderedList<E>& list)
{/*IMPLEMENTATION*/}
friend std::ostream& operator <<(std::ostream& out, const MyOrderedList<E>& list)
{/*IMPLEMENTATION*/}
private:
Node<E>* head;
int size;
};
#endif //MYORDEREDLIST_H
main.cpp
#include <cstdlib>
#include <iostream>
#include "MyOrderedList.h"
using namespace std;
int main(int argc, char** argv)
{
MyOrderedList<int> list;
list.insert(5);
std::cout << list << std::endl;;
return 0;
}
Compiler Error
g++ -o dist/Debug/Cygwin-Windows/project7_windows build/Debug/Cygwin-Windows/main.o
build/Debug/Cygwin-Windows/main.o: In function `_ZN4NodeIiE7getLinkEv':
/cygdrive/c/Users/John/Desktop/Dropbox/Data Structures/Project7 Windows/MyOrderedList.h:(.rdata$_ZTV4NodeIiE[vtable for Node<int>]+0x8): undefined reference to `Node<int>::~Node()'
/cygdrive/c/Users/John/Desktop/Dropbox/Data Structures/Project7 Windows/MyOrderedList.h:(.rdata$_ZTV4NodeIiE[vtable for Node<int>]+0xc): undefined reference to `Node<int>::~Node()'
collect2: ld returned 1 exit status
make[2]: *** [dist/Debug/Cygwin-Windows/project7_windows.exe] Error 1
make[1]: * [.build-conf] Error 2
make: * [.build-impl] Error 2

As your compiler accurately states, you declared ~Node() but never defined it. You need to provide an implementation of Node::~Node().

This
class Node {
virtual ~Node();
};
declares (but does not define) a virtual destructor for Node (the templateness does not matter here). You will either need to
delete this line (thus going with the compiler provided default implementation) or
provide an definition as well:
.
class Node {
virtual ~Node() { /* put your dtor logic here */ }
};
Do not be affraid to delete the declaration uless you are planning to inherit from Node as you cannot put much logic in Node's dtor: it does not know much about its template type. Unless you are planning to delete the pointer to the next node (Node::link), which is probably a dangerous proposition

Related

Error expected constructor, destructor, or type conversion before '.' token

I'm getting 3 errors when compiling my code against my college professors main.cpp
7 0 In file included from main.cpp
3 8 [Error] expected constructor, destructor, or type conversion before '.' token
28 C:\Users\Joe\Desktop\school\Makefile.win recipe for target 'main.o' failed
Here is my ntree.h file
* Ntree.h - header and implementation file for classes Tnode, Ntree //this line is the one getting the error
* Limitations: values cannot contain '(' and ')' characters.
* Can be changed by redefining TOKEN_BEGIN and TOKEN_END
#ifndef _NTREE_H
#define _NTREE_H
#define TOKEN_BEGIN '('
#define TOKEN_END ')'
#include <iostream>
#include <fstream>
#include <cstddef>
#include <vector>
#include <string>
#include <stack>
#include <sstream>
template <typename T>
class Tnode
{
private:
T value;
std::vector<Tnode*> children;
public:
Tnode (T data = {}); // copy constructor
~Tnode(); // destructor
T getValue() const; // gets the value
size_t getChildrenCount() const;
Tnode* getChild(size_t n) const; // get child by number
void setValue(T data); // sets for value
void addChild(Tnode *node); // add child node
void addChild(T data); // creates a node and adds child with a value
bool operator== ( Tnode<T> & other) const; // overload operator
};
template <typename T>
class Ntree{
private:
Tnode<T>* rootPtr;
int numOfNodes;
// utility function get node with current value
Tnode<T>* getNodeByValue(Tnode<T> *node, T data);
// utility function get value from the stream
std::string getToken(std::ifstream & ifs);
void serialize(std::ofstream & ofs, Tnode<T> *node);
public:
Ntree(); // default constructor
Ntree(T val); // constructor with root initialization
~Ntree(); // destructor
void addChildren(T parent, std::initializer_list<T> ini_list);
void serialize(std::string fname);
void deserialize(std::string fname);
bool operator== (Ntree<T> & other);
};
Try Commenting the first 3 lines. Are you sure you know what the first few lines mean?

Problems accessing private data members c++

I have three files: Stack.cc, Stack.h and stacktest.cc . I am not sure about which files to include where, and i am getting different errors because of it. Currently, the code from Stack.h is:
#ifndef STACK_H
#define STACK_H
#include<iostream>
using namespace std;
template<typename T>
class Stack
{
public:
Stack();
void push(int);
void pop();
int top();
int size();
bool empty();
private:
class Element
{
public:
int data;
Element *next;
Element(Element *n, T d) : next{n}, data{d} {}
};
Element *first;
int num;
};
#endif
#include"Stack.cc"
the (relevant, i think) code from Stack.cc is:
#include<iostream>
using namespace std;
template<typename T>
Stack<T>::Stack()
{
first=nullptr;
}
template<typename T>
void Stack<T>::push(int)
{
num++;
first = new Element(first, data);
}
Stacktest is currently just a test file attempting to call the default constructor. The errors i currently get are:
In file included from Stack.h:30:0,
from stacktest.cc:2:
Stack.cc: In member function ‘void Stack<T>::push(int)’:
Stack.cc:22:28: error: ‘data’ was not declared in this scope
first = new Element(first, data);
^
Stack.cc: In function ‘int size()’:
Stack.cc:62:11: error: ‘num’ was not declared in this scope
return num;
For some reason it wont let me access private data members. Before i didnt have the include in the .h file and instead included the .h in Stack.cc, and that worked, although wouldnt let me access the stack class from Stacktest.cc(Stacktest.cc just includes Stack.h)
Any help would be greatly appreciated, thanks.

error: ‘List’ is not a template type

I am a beginner in c++ so please excuse me if I my mistakes below turn out to be silly. Still, I am stuck with my code and would appreciate any help.
I get the following error when trying to compile through make via g++:
In file included from A.cpp:2:
List.h:20: error: ‘List’ is not a template type
A.cpp: In member function ‘void A::NowyObiekt(int)’:
A.cpp:6: error: ‘list_a’ was not declared in this scope
make: *** [A.o] Error 1
My code is separated into the following tiny files:
A.h : http://pastebin.com/QQ04xx2j (header)
A.cpp : below
#include "A.h"
#include "List.h"
void A::NewObject(int i)
{
list_a.Add(i);
}
int A::Compare(int a, int b)
{
if ( a>b ) return 1;
if ( a<b ) return -1;
else return 0;
}
List.h : below (header)
#ifndef LIST_H
#define LIST_H
template<typename T>
class Node
{
Node()
{
nxt = pre = 0;
}
Node(const T& el, Node *n = 0, Node *p = 0 )
{
dana = el; nxt = n; pre = p;
}
T dana;
Node *nxt, *pre;
};
template<typename T>
class List
{
public:
List()
{
head = tail = 0;
}
void Add(const T&);
protected:
Node<T> *head,*tail;
};
#endif
List.cpp : http://pastebin.com/a3HQ9yZ4
prog.cpp : below (main)
#include "List.h"
#include "A.h"
int main()
{
int i = 5;
class List list_a;
class A obj;
obj.Add(i);
}
and the makefile is : http://pastebin.com/GTR5jW54
As noted, I am still a beginner, so please be understanding. I would be thankful for any help and clear explanations. Thanks in advance.
There are a couple of problems with your code: The first is that you don't declare any variable named list_a anywhere. That error should be pretty obvious. The other is that you use the List class without giving it template parameters.
And last a small note about your question: As your files are indeed very small, you could put them in the question and not link to them.
Edit: About the List template problem.
You already use Node properly in List, i.e. declare the nodes as Node<T>. When you use List you simply has to do the same. For example, to declare a list of integers:
List<int> my_int_list;
Also, as you only use public functions in List from the class A, you don't need the friend declaration. If you do need to use protected or private members (which IMO is a sign of bad design) you need to make that friend-declaration templated as well:
friend class List<sometype>;
And finally, your code will not compile anyway... The reason being that when you are using a template-class, the whole class has to be fully defined (i.e. complete with its function implementations). You can solve this by putting the functions in the header file. And when defining the functions, you need the template parameter there as well:
template<typename T>
void List<T>::Add(const T& el)
{
Node<T>* head = new Node<T>(el);
if ( Compare(el,i) > i )
std::cout << "Ok" << std::endl;
}
Note that I added the template parameter in a couple of places.

Error: expected unqualified-id before ‘<’ token

I am trying to make some sort of templated Queue class. It seems ok but I am getting 2 errors in the same line which I can't figure out why. The errors appear in the implementation file .cpp where I am trying to give the definition for the destructor. Here is the code of the header file of the class:
#ifndef QUEUETP_H_INCLUDED
#define QUEUETP_H_INCLUDED
template <class T>
class QueueTp
{
private:
struct Node { T item; struct Node * next;};
enum {QSIZE = 10};
//Queue's head
Node *head;
//Queue's tail
Node *tail;
int size;
int maxsize;
QueueTp(const QueueTp & q);
QueueTp & operator=(const QueueTp & q) { return *this;}
public:
QueueTp(): size(0),head(0),tail(0),maxsize(QSIZE) {};
QueueTp(int q = QSIZE): size(0),head(0),tail(0),maxsize(q) {};
~QueueTp();
bool isEmpty(){return size==0;}
bool isFull() {return size==maxsize;}
int sizecur() {return size;}
bool push(const T& t);
bool pop(T& t);
};
#include "QueueTp.cpp"
#endif // QUEUETP_H_INCLUDED
And here is the definition of the destructor in the implementation file:
#include "QueueTp.h"
#include <iostream>
using namespace std;
typename <class T> //<-<-<- in this line I am getting the two errors
QueueTp<class T>::~QueueTp()
{
Node *ptr;
cout<<endl<<"Deleting the queue...";
while (head !=NULL)
{
ptr = head->next;
delete head;
head = ptr;
}
}
//......other method definitions
The errors are pointed above and the specific error messages I get from the compiler are the ones below.
error: expected nested-name-specifier before ‘<’ token|
error: expected unqualified-id before ‘<’ token|
||=== Build finished: 2 errors, 12 warnings ===||
Please use "template" instead of "typename" on the line where you are getting the two error messages! I find that most of the time, an unidentified keyword or a real keyword in the wrong place often gives errors similar to an undefined type, the next symbol after it would cause an error.

C++ "error: multiple types in one declaration" and "error: expected initializer before 'KeyType'"

When I run the following code...
#ifndef KEYEDITEM_H_INCLUDED
#define KEYEDITEM_H_INCLUDED
#include <string>
typedef std::string KeyType;
class KeyedItem {
public:
KeyedItem() {}
KeyedItem(const KeyType& keyValue) : searchKey(keyValue) {}
KeyType getKey() const
{ return searchKey;
}
private:
KeyType searchKey; };
#endif // KEYEDITEM_H_INCLUDED
I get an error message "error: expected initializer before 'KeyType'"
I thought at first that this could be related to the declaring the string type so I changed it to the following to see if it would work...
#ifndef KEYEDITEM_H_INCLUDED
#define KEYEDITEM_H_INCLUDED
#include <string>
//typedef std::string KeyType;
class KeyedItem
{
public:
KeyedItem() {}
KeyedItem(const std::string& keyValue) : searchKey(keyValue) {}
std::string getKey() const
{ return searchKey;
}
private:
std::string searchKey;
};
#endif // KEYEDITEM_H_INCLUDED
but I got the error "error: multiple types in one declaration" I have looked for errors for both of these errors and have found nothing that helps. I have gone over the class to make sure I have semi-colons where needed and I seem to have all of them.
I don't have a implementation file simply because I didn't need one, but could that be the problem?
This is just a class for a binary search tree. I am working in CodeBlocks using the GNU GCC compiler.
TreeNode.h
#ifndef TREENODE_H_INCLUDED
#define TREENODE_H_INCLUDED
#include "KeyedItem.h"
typedef KeyedItem TreeItemType;
class TreeNode
{
private:
TreeNode() {}
TreeNode(const TreeItemType& nodeItem,
TreeNode *left = NULL,
TreeNode *right = NULL) : item(nodeItem), leftChildPtr(left), rightChildPtr(right) {}
TreeItemType item;
TreeNode *leftChildPtr, *rightChildPtr;
friend class BinarySearchTree;
};
#endif // TREENODE_H_INCLUDED
you need to compile with g++ not gcc
Solved... Turns out I was missing a header include in my main.