【问题标题】:Trouble with Implementing Templates on a Singly Linked List [duplicate]在单链表上实现模板的麻烦[重复]
【发布时间】:2011-11-15 20:26:58
【问题描述】:

可能重复:
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 标题

对象列表.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;

 };

书.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

【问题讨论】:

  • 你的模板ObjectList类的所有方法的实现必须在头文件中(或者至少在你使用ObjectList&lt;Book&gt;类的时候以某种方式包含)
  • 有什么理由不使用std::list&lt;&gt;
  • 我也打算推荐一个 std::list 但这更像是一个 std::set 因为书籍是按字母顺序存储的。
  • @DavidThornley:必须是作业或练习。
  • 糟糕的 C++ 代码。看起来您正在尝试使用 C++ 编写 Java。

标签: c++ list templates linked-list


【解决方案1】:

大概你有,在ObjectList.cpp,定义

template <typename T> void ObjectList<T>::insert(T *)
{ // ...
}

对吗?好吧,问题是编译器无法在不知道作为 T 传入的值的情况下为此生成代码,这通常意味着调用方法的位置。

如果您将模板化类的所有方法体移入内联(到标题中),它将起作用。这是编写 C++ 模板的常用方式:它们都存在于标头中。

【讨论】:

  • 好吧,您可以将实现移动到单独的文件中,但您仍然必须将其包含在标头中,或者导出显式实例化。
  • +1。只需在标头中添加 ObjectList 成员函数的实现即可。您可以将实现与声明一起内联,或者声明您的类并定义实现,但由于 ObjectList 是一个模板类,它必须全部位于标题中。
【解决方案2】:

编译器必须有权访问模板函数的定义,才能为给定的T 值生成适当的实现。惯用的模板函数在头文件中定义。它们可以在别处定义,但无论您在何处使用它们,您都需要包含该文件。最好将其全部粘贴在标题中。

【讨论】:

    【解决方案3】:

    将您的 ObjectList.cpp 重命名为 ObjectList.tpp 并将这一行添加到 ObjectList.h 的最底部

    #include "ObjectList.tpp"
    

    这是一个 hack,允许您将实现保存在单独的文件中,但确保包含您的头文件的任何人也可以获得实现(因为模板系统需要这样的东西)。

    以下是您想要查看的其他内容的列表:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 2013-01-07
      • 2012-02-29
      • 2012-02-04
      • 2023-03-09
      相关资源
      最近更新 更多