C++ 模板类编译“;在‘之前需要构造函数、析构函数或类型转换<’;代币;错误

C++ 模板类编译“;在‘之前需要构造函数、析构函数或类型转换<’;代币;错误,c++,templates,C++,Templates,我在编译模板类时遇到问题。这是我的名单 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

我在编译模板类时遇到问题。这是我的名单

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;
}
使用名称空间std;
模板
列表::列表()
{
长度=0;
}
模板
列表::~List()
{
}
模板
列表和列表::运算符=(常量列表和rhs)
{
列出hha;
返回hha;
}
模板
int List::size()
{
返回长度;
}
这是我的名单

#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
\ifndef\u列表_
#定义列表_
#包括
#包括
使用名称空间std;
模板
班级名单
{
私人:
类ListNode
{
公众:
ListNode();
ListNode(常量T元素);
ListNode*下一步;
T数据;
};
公众:
//大3
List();
~List();
列表和运算符=(常量列表和rhs);
int size();
bool empty();
无效打印(ostream&os)常数;
私人:
ListNode*头;
ListNode*尾部;
整数长度;
};
#包括“list.cpp”
#恩迪夫
当我运行g++list.cpp时

我会犯错误


在“模板实现进入标头之前,需要构造函数、析构函数或类型转换


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

模板实现在标题中


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

因为
list.hpp
没有
#在
list.cpp
中包含
d,当您尝试编译
list.cpp

时,编译器不知道该标头中的模板定义,因为
list.hpp
无法获取
#在
list.cpp
中包含
d,当您尝试编译
list.cpp

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

#include "list.h"
...
但是,这将从本质上导致一个问题:如果您真的想将
列表
用于某种类型,编译器将需要查看使用类模板的模板定义。也就是说,通常您将在头文件中实现模板。另一种方法是在实现文件中实现模板,并显式地实例化要与之一起使用的类型。这对于某些模板来说是相当合理的,但是对于用于未知数量类型的模板来说,这是不实际的


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

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

#include "list.h"
...
但是,这将从本质上导致一个问题:如果您真的想将
列表
用于某种类型,编译器将需要查看使用类模板的模板定义。也就是说,通常您将在头文件中实现模板。另一种方法是在实现文件中实现模板,并显式地实例化要与之一起使用的类型。这对于某些模板来说是相当合理的,但是对于用于未知数量类型的模板来说,这是不实际的


BTW,您使用的名称是不允许触摸的:从下划线开始的名称后面是大写字母,这是为C++实现的,即编译器和标准库。在任何位置使用两个连续下划线的名称也被保留。

您可以编译定义列表成员函数的
list.cpp
。但它不包含模板类声明-即在标题中

我看到您在列表标题中包含了cpp。如果在其他cpp文件中包含列表头,并确保不会将
list.cpp
作为单独的编译单元进行编译,则这将起到一定的作用

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

#include "list.h"
int main()
{}
然后用
g++main.cpp
编译此文件


通常,在完全使用模板时,您只希望避免使用cpp文件。只需在标题中填入所有内容,并将其包括在内。或者,我至少会将您的
list.cpp
重命名为
list.impl
或其他名称。通过这种方式,人们可能不太愿意直接编译该文件。

您可以编译定义列表成员函数的
list.cpp
。但它不包含模板类声明-即在标题中

我看到您在列表标题中包含了cpp。如果在其他cpp文件中包含列表头,并确保不会将
list.cpp
作为单独的编译单元进行编译,则这将起到一定的作用

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

#include "list.h"
int main()
{}
然后用
g++main.cpp
编译此文件

通常,在完全使用模板时,您只希望避免使用cpp文件。只需在标题中填入所有内容,并将其包括在内。或者,我至少会将您的
list.cpp
重命名为
list.impl
或其他名称。通过这种方式,人们可能不太愿意直接尝试编译该文件。

在“一点”之前的许多
可能重复的预期构造函数、析构函数或类型转换中,在“之前的许多
可能重复的预期构造函数、析构函数或类型转换中,在哪一个上”这一部分让我过了一天:我不知道我的朋友在哪里