您的位置:首页 > 编程语言 > C语言/C++

C++模板定义和实现分离导致的编译错误

2016-07-21 20:59 417 查看
今天在实现一个二叉树的时候,用到了模板,没在意,和平时一样写了两个文件:BinaryTree.h,BinaryTree.cpp。思路和平时一样,h文件中定义了模板类,然后在cpp文件中实现了一些功能函数。

然后在test.cpp中测试,遇到了一些问题、

问题出现如下:

使用g++直接编译的时候提示,基本上都是undefined reference to错误:

test_binarytree.cpp:(.text+0x16e): undefined reference to `BinaryTree<std::string>::BinaryTree()'
......


分别编译单独文件,均可生成 .o文件,所以排除单个文件本身的错误

连接两个o文件时,仍然提示上述错误,很明显,连接时,寻找函数出错了。

网上查的资料如下:

编译器不支持 模板类定义和实现的分离,即类定义和实现不能分开放在h头文件和cpp源码文件中;

经过测试,貌似把cpp文件的东西都搬到.h文件中,如果cpp文件还在,都还会提示该问题,所以,除了.h中放实现代码之外,还得把空的cpp文件删除。

从项目中删除后编译成功,但后来重新增加这个.cpp文件,貌似还是能编译成功。

上述的说法亲测正确,但仍有不足,补充资料留作记录:

首先C++中有分离编译的概念:

分离编译模式(Separate Compilation Model) 允许在一处翻译单元中定义(define)函数、类型、类对象等,在另一处翻译单元引用它们。编译器(Compiler)处理完所有翻译单元后,链接器(Linker)接下来处理所有指向 extern 符号的引用,从而生成单一可执行文件。该模式使得 C++ 代码编写得称心而优雅。

然而该模式却驯不服模板(Template)。标准要求编译器在实例化模板时必须在上下文中可以查看到其定义实体;而反过来,在看到实例化模板之前,编译器对模板的定义体是不处理的——原因很简单,编译器怎么会预先知道 typename 实参是什么呢?因此模板的实例化与定义体必须放到同一翻译单元中。

export关键字

标准 C++ 为此制定了“模板分离编译模式(Separation Model)”及 export 关键字。然而由于 template 语义本身的特殊性使得 export 在表现的时候性能很次。

用法此处就不说了,因为C++标准在11中将其丢弃了,所以不建议使用。

另外网上还有一些包含cpp文件的做法之类的,也不做介绍,我觉得不够规范化。因为模板的制定本身就是应该为实例化而开源。所以我比较赞同将模板类的定义和实现放在同一个文件的做法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  cpp c++ 模板 分离编译 g++