可能重复:
Why can templates only be implemented in the header file?
我有一个单独的链接列表,按字母顺序插入新书名并删除它们。我现在正在尝试将其转换为模板程序,以便可以使用除Book之外的其他对象。我已经解决了所有错误,但仍然在使用以下内容进行构建失败:
Undefined symbols for architecture x86_64:
"ObjectList<Book>::insert(Book*)", referenced from:
_main in lib.o ,br>
"ObjectList<Book>::getObjectList(char*)", referenced from:
_main in lib.o
"ObjectList<Book>::delet(Book*)", referenced from:
_main in lib.o
我不太确定我做错了所以这里是代码:
//--------------------------------------------------------------
// lib.cpp
//
//--------------------------------------------------------------
#include <iostream>
using namespace std;
#include "ObjectList.h"
#include "Book.h"
int main(int argc, char* argv[]) {
//--------------------------------------------------------------
// Creates a BookList object, adds several books to the list,
// then prints them.
//--------------------------------------------------------------
char list[2048];
ObjectList<Book> *books = new ObjectList<Book>();
books->insert (new Book("F Title"));
books->insert (new Book("D Title"));
books->insert (new Book("G Title"));
books->insert (new Book("A Title"));
books->insert (new Book("E Title"));
books->insert (new Book("H Title"));
cout << "After inserts:\n";
cout << books->getObjectList(list) << endl;;
//*/
books->delet (new Book("A Title"));
books->delet (new Book("H Title"));
books->delet (new Book("G Title"));
books->delet (new Book("E Title"));
cout << "After deletes:\n";
cout << books->getObjectList(list) << endl;;
books->insert (new Book("A Title"));
books->insert (new Book("E Title"));
books->insert (new Book("H Title"));
books->insert (new Book("G Title"));
cout << "After 2nd inserts:\n";
cout << books->getObjectList(list) << endl;;
//*/
return 0;
}
/ * /当成功运行时,这应该是输出:
插入后:
标题
D标题
E标题
F标题
G标题
H标题
删除后:
D标题
F标题
第二次插入后:
标题
D标题
E标题
F标题
G标题
H标题
ObjectList.h
//********************************************************************
// ObjectListt.h
//
// Represents a collection of books.
//*******************************************************************
#include <iostream>
using namespace std;
template<class T>
class ObjectNode {
public:
//--------------------------------------------------------------
// Sets up the node
//--------------------------------------------------------------
ObjectNode() {}
ObjectNode(T *theObject) {
object = theObject;
next = NULL;
}
friend class ObjectList;
private:
T *object;
ObjectNode *next;
};
template<class T>
class ObjectList {
//----------------------------------------------------------------
// Sets up an empty list of books.
//----------------------------------------------------------------
public:
void add(T *);
void insert(T *);
void delet(T *);
char* getObjectList(char *);
ObjectList() {
head = NULL;
}
private:
ObjectNode<T> *head;
};
Book.h
#include <cstring>
#include <iostream>
using namespace std;
//********************************************************************
// Book.h
//
// Represents a single book.
//*******************************************************************
class Book {
public:
Book (char *newTitle) {
strcpy( title, newTitle );
}
int compareTo(Book *test_book)
{
// comparing test_book to this book
int comparison;
comparison = strcmp(test_book->getObject(), title);
return comparison;
}
//*/
char *getObject() {
return title;
}
private:
char title[81];
};
当程序没有使用模板时,这个程序运行得很好。我没有包含ObjectList.cpp的代码,因为它大约有160行,并且不认为包含它是完全必要的。如果你需要,请告诉我。
对于这个最有可能的菜鸟错误,任何数量的帮助都会受到赞赏。
硬件信息: 2011 15“MacBook Pro运行OS X Lion Netbeans IDE包含所有更新
答案 0 :(得分:4)
据推测,您在ObjectList.cpp
中有
template <typename T> void ObjectList<T>::insert(T *)
{ // ...
}
正确?好吧,问题是如果不知道以T传入的值,编译器就无法生成代码,这通常意味着调用方法的位置。
如果将模板化类的所有方法体内联移动到标题中,它将起作用。这是编写C ++模板的常用方法:它们都存在于标题中。
答案 1 :(得分:1)
编译器必须能够访问模板函数的定义,才能为给定的T
值生成适当的实现。惯用模板函数在头文件中定义。它们可以在别处定义,但无论您在何处使用它们,都需要包含该文件。最好把它全部放在标题中。
答案 2 :(得分:0)
将ObjectList.cpp重命名为ObjectList.tpp,并在ObjectList.h的最底部添加此行
#include "ObjectList.tpp"
这是一个hack,允许您将实现保存在单独的文件中,但确保包含头文件的任何人也获得实现(因为模板系统需要这样的东西)。
以下列出了您想要查看的其他内容:
new
的任何对象也传递给delete
。#include
是在ObjectList.h中的包含保护内容。)strcpy
。这很难正确使用。您应该更喜欢使用<string>
头文件中的类和函数(除非您有非特定原因不这样做,即性能)