This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 8 years ago.
I read many of the other questions about this linker error, but I still wasn't able to solve it yet...
vector.hpp
#ifndef vector_hpp
#define vector_hpp
namespace vec
{
template<class T> class Vector
{
private:
T* arr;
unsigned int numberOfElements;
public:
Vector();
~Vector();
void push_back(const T&);
void pop_back();
void pop_front();
unsigned int size() const;
T& at(int);
T& front();
bool empty() const;
T& operator[](const int) const;
};
}
#endif
vector.cpp (not everything, would be too long)
#include "vector.hpp"
#include <iostream>
namespace vec
{
template<class T>
Vector<T>::Vector()
: arr(nullptr), numberOfElements(0)
{
return;
}
template<class T>
Vector<T>::~Vector()
{
delete[] arr;
}
template<class T>
unsigned int Vector<T>::size() const
{
return numberOfElements;
}
...
}
patientenliste.hpp
#ifndef patientenliste_hpp
#define patientenliste_hpp
#include "vector.hpp"
#include <iostream>
#include "patient.hpp"
using namespace std;
class Patientenliste
{
private:
vec::Vector<Patient> liste;
public:
Patientenliste& operator+= (const Patient&);
vec::Vector<Patient>& getPListe();
friend ostream& operator<< (ostream&, const Patientenliste&);
};
ostream& operator<< (ostream&, const Patientenliste&);
#endif
patientenliste.cpp
#include "patientenliste.hpp"
Patientenliste& Patientenliste::operator+= (const Patient& p)
{
liste.push_back(p);
return *this;
}
vec::Vector<Patient>& Patientenliste::getPListe()
{
return liste;
}
ostream& operator<< (ostream& os, const Patientenliste& p)
{
if(p.liste.size() == 0)
os << "Keine Patienten in der Liste.";
else
for(unsigned int i=0; i < p.liste.size(); i++)
os << p.liste[i] << endl;
return os;
}
I have some more files/classes in my project but every class which uses my Vector-class I get the Linker-error:
patientenliste.cpp:(.text+0x32): Nicht definierter Verweis auf vec::Vector<Patient>::size() const'
patientenliste.cpp:(.text+0x5e): Nicht definierter Verweis aufvec::Vector::size() const'
patientenliste.cpp:(.text+0x6c): Nicht definierter Verweis auf `vec::Vector::operator [ ] (int) const'
(in english "Nicht definierter Verweis auf" means "undefined reference to")
I have absolutely no clue about what's going wrong...
I already tried it wihtout the namespace vec, but that didn't work either.
Template definitions shall be in the same header file where the corresponding template class is defined.
Related
This question already has answers here:
Undefined reference to destructor error in c++?
(2 answers)
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 11 months ago.
I have a AVL class like this, it's templated and it gives error in main, I have tried to debug it for hours but it didn't fixed. What can be the problem? What part am I missing? It can be related to constructors but I tried that and it didn't fixed. I'm using Visual Studio 2012 and I feel stuck.
The error is:
1>Ege_HW2.obj : error LNK2019: unresolved external symbol "public: __thiscall AvlTree<struct item>::~AvlTree<struct item>(void)" (??1?$AvlTree#Uitem####QAE#XZ) referenced in function __unwindfunclet$??0AVLSection##QAE#XZ$0
1>Ege_HW2.obj : error LNK2019: unresolved external symbol "public: __thiscall AvlTree<struct AVLSection>::~AvlTree<struct AVLSection>(void)" (??1?$AvlTree#UAVLSection####QAE#XZ) referenced in function _main
1>fatal error LNK1120: 2 unresolved externals
Header file:
#ifndef AVLTREE_H
#define AVLTREE_H
#include <iostream>
#include <string>
using namespace std;
/* AVL Tree is taken from the lecture slides. */
template <class Comparable>
class AvlTree;
template <class Comparable>
class AvlNode
{
Comparable element;
AvlNode* left;
AvlNode* right;
int height;
AvlNode(const Comparable& theElement,
AvlNode* lt, AvlNode* rt, int h = 0)
: element(theElement), left(lt), right(rt), height(h) { }
friend class AvlTree<Comparable>;
};
template <class Comparable>
class AvlTree
{
public:
explicit AvlTree();
explicit AvlTree(const Comparable& notFound);
AvlTree(const AvlTree& rhs);
~AvlTree();
const Comparable& findMin() const;
const Comparable& findMax() const;
const Comparable& find(const Comparable& x) const;
bool isEmpty() const;
void printTree() const;
void makeEmpty();
void insert(const Comparable& x);
void remove(const Comparable& x);
const AvlTree& operator=(const AvlTree& rhs);
private:
AvlNode<Comparable>* root;
const Comparable ITEM_NOT_FOUND;
const Comparable& elementAt(AvlNode<Comparable>* t) const;
void insert(const Comparable& x, AvlNode<Comparable>*& t) const;
void remove(const Comparable& x, AvlNode<Comparable>*& t) const;
AvlNode<Comparable>* findMin(AvlNode<Comparable>* t) const;
AvlNode<Comparable>* findMax(AvlNode<Comparable>* t) const;
AvlNode<Comparable>* find(const Comparable& x, AvlNode<Comparable>* t) const;
void makeEmpty(AvlNode<Comparable>*& t) const;
void printTree(AvlNode<Comparable>* t) const;
AvlNode<Comparable>* clone(AvlNode<Comparable>* t) const;
// Avl manipulations
int height(AvlNode<Comparable>* t) const;
int max(int lhs, int rhs) const;
void rotateWithLeftChild(AvlNode<Comparable>*& k2) const;
void rotateWithRightChild(AvlNode<Comparable>*& k1) const;
void doubleWithLeftChild(AvlNode<Comparable>*& k3) const;
void doubleWithRightChild(AvlNode<Comparable>*& k1) const;
};
#include "AvlTree.cpp"
#endif
Cpp file:
#include "avlTree.h"
#include <iostream>
using namespace std;
template <class Comparable>
AvlTree<Comparable>::AvlTree(){
root = NULL;
}
/*** Construct the tree.
*/
template <class Comparable>
AvlTree<Comparable>::AvlTree(const Comparable& notFound)
:ITEM_NOT_FOUND(notFound), root(NULL){}
/*** Copy constructor.*/
template <class Comparable>
AvlTree<Comparable>::AvlTree(const AvlTree<Comparable>& rhs)
: root(NULL), ITEM_NOT_FOUND(rhs.ITEM_NOT_FOUND) {
*this = rhs;
}
And finally the main:
#include <iostream>
#include <string>
#include "BinaryTree.h"
#include "AvlTree.h"
#include <fstream>
using namespace std;
struct item{
string title;
string information;
item(){};
};
struct AVLSection{
AvlTree<item> avlSection;
string sectionTitle;
AVLSection(){};
};
struct BSTSection{
BinarySearchTree <item> bstSection;
string sectionTitle;
BSTSection(){}
};
void readData(BinarySearchTree<BSTSection> & bst, AvlTree<AVLSection> & avl){
ifstream input;
string filename = "data.txt",line;
input.open(filename.c_str());
while(getline(input,line)){
cout << line;
}
}
int main(){
BinarySearchTree<BSTSection> bst;
AvlTree<AVLSection> avl;
}
I am writing two templated classes (for academic reasons):
'class Vector', which mimics a C++ vector using a dynamic array.
'class Set', which creates a set using a vector object.
Vector.cpp -
#ifndef __CS_VECTOR_H_
#define __CS_VECTOR_H_
#include <cstdlib>
#include "Set.cpp"
template <class Type>
class Vector
{
public:
Vector(unsigned int capacity = DEFAULT_CAPACITY);
Vector(const Vector<Type>& rhs);
~Vector();
unsigned int capacity() const;
unsigned int size() const;
bool empty() const;
void push_back(const Type& data);
bool remove(const Type& data);
void clear();
bool at(unsigned int pos, Type& data) const;
int get_array_size() const;
Type& operator[](unsigned int pos) const;
Vector& operator=(const Vector& rhs);
private:
static const unsigned int DEFAULT_CAPACITY = 3;
void generate_larger_array(unsigned int capacity);
int array_size_ = 0;
int array_capacity_;
Type *array_;
};
//Function definitions here.
//#include "Set.cpp"
#endif
Set.cpp -
#ifndef __CS_SET_H_
#define __CS_SET_H_
#include "Vector.cpp"
template <class Comparable>
class Set
{
public:
unsigned int size() const;
bool empty() const;
bool contains(const Comparable& data) const;
bool insert(const Comparable& data);
bool remove(const Comparable& data);
void clear();
int get_size();
private:
int element_;
Vector<Comparable> set_;
};
//Function definitions here
//#include "Vector.cpp"
#endif
Main.cpp
#include "Set.cpp"
#include "Vector.cpp"
When I compile my code, I receive an error telling me:
error: ‘Vector’ does not name a type Vector<Comparable> set_;
When declaring my set_ object in Set.
These are both cpp files that are included into a file main.cpp. The set cpp file does contain the #include vector.cpp and vice versa
main.cpp just has code that tests the class functionality. I receive this error when attempting to compile either the main.cpp file. The main.cpp file is written by my instructor, so I am not entirely sure I should post it here.
The issue I'm having here is class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Sadrzaj const &). I have searched far and wide on the Internet for a solution but could not find it. The issue occurs when I try to include Data.h in the main source file, the same happens with Content.h. Down below are the two header files for reference. Any help whatsoever is greatly appreciated. :-)
#pragma once
#include <iostream>
class Content
{
friend std::ostream& operator<<(std::ostream &str, const Content&);
public:
virtual void print(std::ostream&) const = 0;
};
std::ostream& operator<<(std::ostream &str, const Content& temp)
{
temp.print(str);
return str;
}
#pragma once
#include "Content.h"
template <class T>
class Data: public Content
{
public:
Data(const T&);
void print(std::ostream&) const override;
private:
T data;
};
template <class T>
Data<T>::Data(const T& data) : data(data) {}
template <class T>
void Data<T>::print(std::ostream& str) const { str << data; }
Okay, so the problem was that the << operator was defined in the "Content.h" header file. Simply by creating a new source file "Content.cpp" and defining it there, the problem was solved. If anyone knows why this solved the error, I would appreciate it very much if they would explain it to me, so that I don't make the same mistake again. :-)
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 7 years ago.
The solution to the duplicate question did not work
I have the following files:
ListaEnc.hpp
#include "Elemento.hpp"
template<typename T>
class ListaEnc {
public:
ListaEnc();
~ListaEnc();
// inicio
void adicionaNoInicio(const T& dado);
T retiraDoInicio();
void eliminaDoInicio();
T pegarHead();
// posicao
void adicionaNaPosicao(const T& dado, int pos);
int posicao(const T& dado) const;
T* posicaoMem(const T& dado) const;
bool contem(const T& dado);
T retiraDaPosicao(int pos);
// fim
void adiciona(const T& dado);
T retira();
// especifico
T retiraEspecifico(const T& dado);
void adicionaEmOrdem(const T& data);
// outras
bool listaVazia() const;
bool igual(T dado1, T dado2);
bool maior(T dado1, T dado2);
bool menor(T dado1, T dado2);
void destroiLista();
int pegarTamanhoLista();
private: //trocar pra private
Elemento<T>* head;
int size;
};
ListaEnc.cpp
#include "ListaEnc.hpp"
#include <cstdlib>
#include <iostream>
template<typename T>
ListaEnc<T>::ListaEnc()
{
...
}
main.cpp
#include "ListaEnc.hpp"
using namespace std;
int main(int argc, char** argv)
{
double x1, y1;
x1 = 2; y1 = 4.2;
ListaEnc<int>* teste = new ListaEnc<int>();
return 0;
}
This should compile just fine, but I get an undefined reference error to ListaEnc on main.cpp. I have more files in which the reference to ListaEnc is also undefined, but I tried isolating it and still can't get it to work. Does anyone understand why this is happening?
edit: More specifically, there is an undefined error to the constructor and destructor of ListaEnc
You can't separate declaration from implementation when you instantiate a template class. Combine your code to a single file and include that in your main.cpp.
Or, even go a step further and implement the functions inline in your class declaration if that suits your coding style.
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