Well, i'm trying to build a project in c++ but I got an undefined error while I'm using a template for a derived class:
The project are defined as the following:
|_bin
|_include
| |_Items.h
| |_Lists.h
|_src
|_main.cpp
|_lists.cpp
|_items.cpp
The code:
Items.h
#ifndef ITEMS_H
#define ITEMS_H
#include <iostream>
using namespace std;
namespace Lists {
template <class T>
class LinkedList;
}
namespace Items {
template <class T>
class Item {
public:
Item() = default;
Item(T id);
void SetId(T id) { this->id = id; }
T GetId() { return this->id; }
virtual void Print() const {};
protected:
T id;
};
template <class T>
class ItemConsciousness: public Item<T> {
public:
ItemConsciousness() = default;
ItemConsciousness(T id): Item<T>(id) {};
ItemConsciousness(T id, string data, string msg);
void SetData(string data) {this->data = data;}
string GetData() { return this->data; }
void SetMsg(string msg) {this->msg = msg;}
string GetMsg() { return this->msg; }
void Print();
private:
string data;
string msg;
};
template <class T>
class Node {
public:
Node() = default;
Node(Item<T> item, Node* next);
private:
Item<T> item;
Node* prox;
friend class Lists::LinkedList<T>;
};
}
#endif
Items.cpp
#include "Items.h"
#include <iostream>
using namespace Items;
using namespace std;
template <class T>
Item<T>::Item(T id){
this->id = id;
}
template <class T>
ItemConsciousness<T>::ItemConsciousness(T id, string data, string msg) {
this->SetId(id);
this->SetData(data);
this->SetMsg(msg);
};
template <class T>
void ItemConsciousness<T>::Print() {
cout << this->data << " " << this->msg << endl;
}
template <class T>
Node<T>::Node(Item<T> item, Node* next){
this->item = item;
this->next = next;
}
Lists.h
#ifndef LISTS_H
#define LISTS_H
#include "Items.h"
#include <iostream>
using namespace std;
using namespace Items;
namespace Lists {
template<class T>
class List {
public:
List() {this->size = 0;};
int GetSize() {return size;};
bool IsEmpty() {return size == 0;};
virtual Item<T> GetItem(int pos) = 0;
virtual void SetItem(Item<T>, int pos) = 0;
virtual void InsertStart(Item<T> item) = 0;
virtual void InsertEnd(Item<T> item) = 0;
virtual void InsertPosition(Item<T> item, int pos) = 0;
virtual Item<T> RemoveStart() = 0;
virtual Item<T> RemoveEnd() = 0;
virtual Item<T> RemovePosition(int pos) = 0;
virtual Item<T> Search(T c) = 0;
virtual void Print() = 0;
virtual void Clear() = 0;
protected:
int size;
};
template<class T>
class LinkedList: public List<T> {
private:
Node<T>* first;
Node<T>* last;
Node<T>* Position(int pos, bool is_before = false);
public:
LinkedList();
~LinkedList();
Item<T> GetItem(int pos);
void SetItem(Item<T> item, int pos);
void InsertStart(Item<T> item);
void InsertEnd(Item<T> item);
void InsertPosition(Item<T> item, int pos);
Item<T> RemoveStart();
Item<T> RemoveEnd();
Item<T> RemovePosition(int pos);
Item<T> Search(T c);
void Print();
void Clear();
};
}
#endif
Lists.cpp
#include "Lists.h"
#include "Items.h"
#include <iostream>
using namespace Items;
using namespace Lists;
using namespace std;
template<class T>
LinkedList<T>::LinkedList() { // O(1)
this->size = 0;
first = new Node<T>();
last = first;
}
template<class T>
LinkedList<T>::~LinkedList() { // O(n)
this->Clear();
delete this->first;
}
template<class T>
void LinkedList<T>::Clear() { // O(n)
Node<T> *p;
p = this->first->next;
while(p!=NULL) {
this->first->next = p->next;
delete p;
p = this->first->next;
}
this->last = this->first;
this->size = 0;
}
template<class T>
Node<T>* LinkedList<T>::Position(int pos, bool is_before) { // Best Case O(1) and Worse O(n)
Node<T>* p;
int i;
if((pos > this->size) || (pos <= 0)){
throw "ERROR: Invalid Position!";
}
p = this->first;
for(i=1; i<pos; i++) {
p = p->next;
}
if(!is_before) {
p = p->next;
}
return p;
}
template<class T>
Item<T> LinkedList<T>::GetItem(int pos) { // Best Case O(1) and Worse O(n)
Node<T>* p;
p=this->Position(pos);
return p->item;
}
template<class T>
void LinkedList<T>::SetItem(Item<T> item, int pos) {// Best Case O(1) and Worse O(n)
Node<T>* p;
p = this->Position(pos);
p->item = item;
}
template<class T>
void LinkedList<T>::InsertStart(Item<T> item) { // Custo O(1)
Node<T>* new_node;
new_node = new Node<T>();
new_node->item = item;
new_node->next = this->first->next;
this->first->next = new_node;
this->size++;
if (new_node->next == NULL) {
this->last = new_node;
}
};
template<class T>
void LinkedList<T>::InsertEnd(Item<T> item) { // Custo O(1)
Node<T>* new_node;
new_node = new Node<T>();
new_node->item = item;
this->last->next = new_node;
this->last = new_node;
this->size++;
};
template<class T>
void LinkedList<T>::InsertPosition(Item<T> item, int pos) {// Best Case O(1) and Worse O(n)
Node<T>* p, *new_node;
p = Position(pos, true);
new_node = new Node<T>();
new_node->item = item;
new_node->next = p->next;
p->next = new_node;
this->size++;
if (new_node->next == NULL) {
this->last = new_node;
}
}
template<class T>
Item<T> LinkedList<T>::RemoveStart() { // O(1)
Item<T> aux;
Node<T>* p;
if(this->size== 0) {
throw "ERROR: Empty List!";
}
p = this->first->next;
this->first->next = p->next;
this->size--;
if(this->first->next == NULL) {
this->last = this->first;
}
aux = p->item;
delete p;
return aux;
}
template<class T>
Item<T> LinkedList<T>::RemoveEnd() { // O(n)
Item<T> aux;
Node<T>* p;
if (this->size == 0) {
throw "ERROR: Empty List!";
}
p = this->Position(this->size, true);
p->next = NULL;
this->size--;
aux = last->item;
delete last;
this->last = p;
return aux;
}
template<class T>
Item<T> LinkedList<T>::RemovePosition(int pos) { // Best: O(1), Worse: O(n)
Item<T> aux;
Node<T> *p, *q;
if(this->size ==0)
throw "ERROR: Empty List!";
p = this->Position(pos, true);
q = p->next;
p->next = q->next;
this->size--;
aux = q->item;
delete q;
if (p->next == NULL) {
this->last = p;
}
return aux;
}
template<class T>
Item<T> LinkedList<T>::Search(T c) { // Best: O(1), Worse: O(n)
Item<T> aux;
Node<T>* p;
if(this->size == 0) {
throw "ERROR: Empty List!";
}
p = this->first->next;
aux.SetChave(-1);
while(p!=NULL) {
if(p->item.GetId() == c) {
aux = p->item;
break;
}
p=p->next;
}
return aux;
}
template<class T>
void LinkedList<T>::Print() { // O(n)
Node<T>* p;
p = this->first->next;
while(p!=NULL) {
p->item.Print();
p = p->next;
}
};
main.cpp
#include <iostream>
#include "Items.h"
#include "Lists.h"
using namespace std;
using namespace Items;
using namespace Lists;
int main() {
int num_servers;
cin >> num_servers;
LinkedList<int> server_buffer;
Item<int> i;
ItemConsciousness<int> user1;
Node<int> n;
}
Command to compile and run:
g++ -Wall -Wextra -std=c++11 -ggdb -Iinclude -Llib src/Lists.cpp src/Items.cpp src/main.cpp -o bin/main
The error that I got:
/usr/bin/ld: /tmp/ccu3TkFa.o: in function `main':
/mnt/c/Users/lauro/VERLAB/src/main.cpp:16: undefined reference to `Lists::LinkedList<int>::LinkedList()'
/usr/bin/ld: /mnt/c/Users/lauro/VERLAB/src/main.cpp:16: undefined reference to `Lists::LinkedList<int>::~LinkedList()'
/usr/bin/ld: /mnt/c/Users/lauro/VERLAB/src/main.cpp:16: undefined reference to `Lists::LinkedList<int>::~LinkedList()'
collect2: error: ld returned 1 exit status
make: *** [Makefile:20: bin/main] Error 1
The terminal process "bash '-c', 'bash -c 'make run''" terminated with exit code: 2.
I don't know why these errors are occurring...
And a interesting point is that, if a change the main.cpp
to:
#include <iostream>
#include "Items.h"
#include "Lists.h"
using namespace std;
using namespace Items;
using namespace Lists;
int main() {
int num_servers;
cin >> num_servers;
LinkedList<int> server_buffer();
Item<int> i;
ItemConsciousness<int> user1;
Node<int> n;
}
The code runs perfectly without any errors.
Aucun commentaire:
Enregistrer un commentaire