包含.cpp文件?

16

可能是重复的问题:
为什么只能在头文件中实现模板(template)?

最近我在尝试使用C++编程。目前我正在尝试编写一个简单的链表类,相信每个人都至少做过一次。 代码已经完成,但我似乎无法编译它。我已经搜索了谷歌,看起来像是我链接对象文件不正确。这就是我的代码基本结构:

test.cpp

#include "linkedlist.h"

int main()
{
    LinkedList<int> list;
    // do something
}

链表头文件 linkedlist.h

template <typename T>
class LinkedList
{
   // a lot of function and variable definitions
}

然后有一个名为linkedlist.cpp的.cpp文件,其中包含LinkerList类的所有实际代码。当尝试使用以下命令编译test.cpp时:

g++ ..\src\test.cpp

我被告知出现了“LinkedList::LinkedList()”的未定义引用。因此,我认为由于存在多个.cpp文件,它们的链接方式不正确,所以我尝试了以下方法:

g++ -c -Wall -O2 ..\src\test.cpp
g++ -c -Wall -O2 ..\src\linkedlist.cpp
g++ -s test.o linkedlist.o

然而,这并没有改变什么。错误消息仍然是一样的。 我一直在尝试在互联网上找到一些信息,然而,它并没有真正起到作用。


3
做得好,完整而连贯地表达出来。 :) 现在的新手很少能做到这一点。 :( - Lightness Races in Orbit
由于LinkedList是一个模板类,该类的用户需要所有方法的完整定义。一种方法是将所有方法内联在类中,另一种方法是将方法放在单独的文件中并将其包含在头文件中。 - Some programmer dude
@Mike:很难说那是一个“重复”的问题。这就是事情变得模糊的地方——尽管我们不需要再次涵盖相同的内容,但问题完全不同。 :) - Lightness Races in Orbit
@MikeSeymour:这可是个很棘手的问题。Stack Overflow上有很多答案可能适用于完全不相关的问题!不过,我只是在刁难而已。 - Lightness Races in Orbit
正如我所说的,我在决定在这里询问之前寻找了一段时间的答案。虽然它涵盖了同样的问题,但我不知道这可能是原因。可能是因为我之前使用过VS10而不是g++,并且在那里它工作得非常好。 - haiyyu
显示剩余2条评论
5个回答

6
您正在创建一个类模板,其中一个重要的注意事项是所有变量定义必须放置在头文件中,以便在编译期间对所有翻译单元都可访问。原因在于模板的工作方式。在编译期间,编译器根据类模板定义实例化模板类。仅有访问声明或签名是不够的:它需要整个定义。
将所有方法定义从 .cpp 文件移到 .h 文件中,一切就会正常(假设您已经提供了默认构造函数的定义!)。或者,您可以通过明确告诉编译器使用 template class LinkedList 之类的东西来绕过这个问题,但在这种简单情况下,这真的不是必需的。这种方法的主要优点是可能减少代码膨胀并加快编译速度。但在编译器适当应用优化的情况下,这完全不必要。

2
“export” 关键字已不再存在,在此之前其支持也相当有限。 - Lightness Races in Orbit

2
你将类 LinkedList 分成了声明和定义两个文件,声明在头文件中,而定义在源文件中。这种做法对于模板是行不通的(点此了解详情)。对于模板,两者都必须在头文件中。

他确实说过 然后有一个名为linkedlist.cpp的.cpp文件,其中包含LinkerList类的所有实际代码。 - Lightness Races in Orbit
这就是我只是匆匆浏览问题的结果 - 我已经修复了它。 - Björn Pollex
你问这样的问题是可以被原谅的 ;) - Lightness Races in Orbit

1

由于LinkedList是一个类模板,其成员函数的定义应该放在头文件中

(严格来说,它们不必如此,但这是绕过模板实例化复杂性而不完全偏离包含约定的最简单方法。)

哦,无论如何,您都需要采取第二种构建方法;您应该链接所有 .cpp 文件,或使用-c开关逐个编译,然后稍后将结果链接在一起。


1

模板类就像是一个规则的定义,用于构建实际的类。实际的类是由编译器在模板类实例化的地方创建(实例化)。因此,在那个点上,模板类的所有代码必须对编译器可见,这就是为什么您必须将所有模板函数和方法编写在头文件中的原因 - 因为您只将头文件包含到cpp文件中,只有头文件在那个点上对编译器可见。您不会将cpp文件包含到另一个cpp文件中,也永远不应该这样做。

如果我的理解有误,请纠正我。

P.S. C++11是否解决了这个问题?


1
不,它没有。C++03试图并失败了,所以C++11放弃了并实际上删除了这个尝试。 - Lightness Races in Orbit

0
“LinkedList::LinkedList()”存在未定义的引用。
你是否检查过你的LinkedList类是否有构造函数?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接