关于c ++:模板类编译“期望构造函数,析构函数或’<’令牌之前的类型转换”错误

Template class compilation “expected constructor, destructor, or type conversion before ‘<’ token” error

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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;
}

这是我的单子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#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时

我得到错误

"<"标记之前需要构造函数、析构函数或类型转换

对于构造函数、析构函数和运算符的定义…

我不知道怎么了


模板实现放在头中。

这是一个有点黑客,但它是如何做到的。


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

1
2
#include"list.h"
...

但是,这实际上会导致出现一个问题:如果您真的想将List与某些类型一起使用,编译器将需要查看使用类模板的模板定义。也就是说,通常您将在头文件中实现模板。alterntaive是在实现文件中实现模板,并显式地实例化要与之一起使用的类型。对于某些模板来说,这是相当合理的,但是对于一些打算用于未知类型的东西来说,这是不实际的。

顺便说一下,你使用的名字是不允许触摸的:从下划线开始的名字后面是大写字母,这是C++实现的,也就是编译器和标准库。在任何地方使用两个连续下划线的名称也被保留。


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

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

我的意思是,文件main.cpp:

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

然后用g++ main.cpp编译这个。

通常,您只想在一起使用模板时避免使用cpp文件。把所有的东西都塞在头上,包括在内。或者我至少把你的list.cpp改名为list.impl或其他名字。这样一来,人们就不太愿意尝试直接编译该文件了。


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