我在编译模板类时遇到问题。这是我的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;
}
这是我的list.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
时我收到错误
在'&lt;'标记
之前的预期构造函数,析构函数或类型转换用于构造函数,析构函数和运算符的定义......
我不知道什么是错的
答案 0 :(得分:2)
模板实现在标题中。
这有点像黑客,但它是如何完成的。
答案 1 :(得分:1)
您目前遇到的问题是list.cpp
不包括list.h
:编译器会看到一些尚未声明的事物的定义。您可以通过在文件顶部添加list.h
来解决此问题:
#include "list.h"
...
然而,这实际上会导致出现问题:如果您确实想要使用某种类型的List<T>
,编译器将需要查看使用类模板的模板定义。也就是说,通常您将在头文件中实现模板。该替代方法是在实现文件中实现模板,并显式实例化它要使用的类型。对于某些模板来说这是非常合理的,但对于那些用于未知数量类型的东西,这是不切实际的。
顺便说一句,您使用的是不允许触摸的名称:以下划线后跟大写字母开头的名称保留给C ++实现,即编译器和标准库。在任何地方使用两个连续下划线的名称也是保留的。
答案 2 :(得分:0)
由于list.hpp
未在#include
中获得list.cpp
d,因此当您尝试编译list.cpp
时,编译器不知道该标头中的模板定义。
答案 3 :(得分:0)
编译list.cpp
,定义列表成员函数。但它不包含模板类声明 - 即在标题中。
我看到你在列表标题中包含cpp。如果在其他cpp文件中包含列表标题,并确保list.cpp
不会编译为单独的编译单元,这将有用。
我的意思是文件main.cpp:
#include "list.h"
int main()
{}
然后使用g++ main.cpp
编译它。
通常,您只想在完全使用模板时避免使用cpp文件。只需填写标题中的所有内容即可。或者,我至少会将您的list.cpp
重命名为list.impl
或其他名称。通过这种方式,人们可能不太愿意直接尝试编译该文件。