【问题标题】:Template class compilation "expected constructor, destructor, or type conversion before ‘<’ token" error模板类编译“预期构造函数、析构函数或‘<’标记之前的类型转换”错误
【发布时间】:2012-02-26 21:37:35
【问题描述】:

我在编译模板类时遇到问题。这是我的 list.cpp

using namespace std;

template <class T>
List<T>::List()
{
    length = 0;
}

template <class T>
List<T>::~List()
{

}


template <class T>
List<T> & List<T>::operator=(const List<T> & rhs)
{
    List<T> hha;
    return hha;
}


template <class T>
int List<T>::size()
{
    return length;
}

这是我的清单。h

#ifndef _LIST_H_
#define _LIST_H_

#include <iterator>
#include <ostream>

using namespace std;

template <class T>
class List
{
    private:

        class ListNode
        {
            public:
                ListNode();
                ListNode(const T element);

                ListNode *next;
                T data;
        };

    public:

        // big3
        List();
        ~List();
        List<T> & operator=(const List<T> & rhs);

        int size();
        bool empty();
        void print(ostream & os) const;


    private:
        ListNode * head;
        ListNode * tail;
        int length;
};

#include "list.cpp"

#endif

当我运行 g++ list.cpp

我收到错误

构造函数、析构函数和运算符的定义...

不知道怎么回事

【问题讨论】:

标签: c++ templates


【解决方案1】:

模板实现放在标题中。

这有点小技巧,但它就是这样做的。

【讨论】:

  • 那“一点”部分让我很开心:D
  • 我不知道我对使用 std::list 优先于您自己的实现的看法在哪里,但您可能应该接受这个建议。
【解决方案2】:

您当前遇到的问题是您list.cpp 不包括您list.h:编译器会看到一些尚未声明的事物的定义。您可以通过在文件顶部包含 list.h 来解决此问题:

#include "list.h"
...

然而,这本质上会导致一个问题:如果你真的想将List&lt;T&gt; 用于某种类型,编译器将需要查看使用类模板的模板定义。也就是说,通常您将在头文件中实现您的模板。另一种方法是在实现文件中实现模板并显式实例化要使用的类型。这对于某些模板来说是相当合理的,但对于打算用于未知数量类型的模板来说这是不切实际的。

顺便说一句,您正在使用不允许触摸的名称:以下划线后跟大写字母开头的名称保留用于 C++ 实现,即编译器和标准库。在任何地方使用两个连续下划线的名称也是保留的。

【讨论】:

    【解决方案3】:

    由于list.hpplist.cpp 中没有得到#included,因此当您尝试编译list.cpp 时,编译器不知道该标头中的模板定义。

    【讨论】:

      【解决方案4】:

      您编译list.cpp,它定义了您的列表成员函数。但它不包含模板类声明 - 位于标题中。

      我看到您在列表标题中包含 cpp。如果您在其他一些 cpp 文件中包含列表头并确保 list.cpp 不会被编译为单独的编译单元,这将有点工作。

      我的意思是文件 main.cpp:

      #include "list.h"
      int main()
      {}
      

      然后用g++ main.cpp编译它。

      通常您只想在完全使用模板时避免使用 cpp 文件。只需将所有内容都放在标题中并包含它。或者,我至少会将您的 list.cpp 重命名为 list.impl 或其他名称。这样一来,人们可能不太愿意尝试直接编译该文件。

      【讨论】:

      • 我刚刚编译了 main.cpp,没有更改上面的任何代码,它运行正常,哈哈。谢谢!
      • @wayfare 很高兴我能帮上忙 :) 顺便说一句。如果它对您的问题有帮助(或接受最有帮助的答案),则习惯上接受答案。这也适用于您的其他问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-04
      • 2016-03-14
      • 2014-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      相关资源
      最近更新 更多