在单链接列表上实现模板的麻烦

时间:2011-11-15 20:26:58

标签: c++ list templates linked-list

  

可能重复:
  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包含所有更新

3 个答案:

答案 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,允许您将实现保存在单独的文件中,但确保包含头文件的任何人也获得实现(因为模板系统需要这样的东西)。

以下列出了您想要查看的其他内容:

  1. 您需要确保new的任何对象也传递给delete
  2. 使用标头包含保护是个好主意(只需确保我在上面提到的#include是在ObjectList.h中的包含保护内容。)
  3. 避免像瘟疫一样strcpy。这很难正确使用。您应该更喜欢使用<string>头文件中的类和函数(除非您有非特定原因不这样做,即性能)