转:C++模板定义和实现分离导致的编译错误
2017-03-04 21:04
489 查看
原文地址:
http://blog.csdn.net/gvfdbdf/article/details/51986630
今天在实现一个二叉树的时候,用到了模板,没在意,和平时一样写了两个文件:BinaryTree.h,BinaryTree.cpp。思路和平时一样,h文件中定义了模板类,然后在cpp文件中实现了一些功能函数。
然后在test.cpp中测试,遇到了一些问题、
问题出现如下:
使用g++直接编译的时候提示,基本上都是undefined reference to错误:
2
1
2
分别编译单独文件,均可生成 .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文件的做法之类的,也不做介绍,我觉得不够规范化。因为模板的制定本身就是应该为实例化而开源。所以我比较赞同将模板类的定义和实现放在同一个文件的做法。
http://blog.csdn.net/gvfdbdf/article/details/51986630
今天在实现一个二叉树的时候,用到了模板,没在意,和平时一样写了两个文件:BinaryTree.h,BinaryTree.cpp。思路和平时一样,h文件中定义了模板类,然后在cpp文件中实现了一些功能函数。
然后在test.cpp中测试,遇到了一些问题、
问题出现如下:
使用g++直接编译的时候提示,基本上都是undefined reference to错误:
test_binarytree.cpp:(.text+0x16e): undefined reference to `BinaryTree<std::string>::BinaryTree()' ......1
2
1
2
分别编译单独文件,均可生成 .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文件的做法之类的,也不做介绍,我觉得不够规范化。因为模板的制定本身就是应该为实例化而开源。所以我比较赞同将模板类的定义和实现放在同一个文件的做法。
相关文章推荐
- C++模板定义和实现分离导致的编译错误
- C++模板定义与实现分离所导致的链接错误LNK2019
- C++模板的声明与实现分离 编译错误详解
- C++模板声明定义分离编译错误详解
- c++模板函数声明定义分离编译错误详解
- C++模板应用——让模板定义和实现分离的方法
- 【c++模板】模拟实现有模板的双向链表(List)(声明和定义分离)
- C++模板编程:如何使非通用的模板函数实现声明和定义分离
- C++类模板定义与实现的分离—学习C++数据抽象和问题求解
- c++模板函数声明定义分离编译错误详解
- c++模板函数声明定义分离编译错误详解
- c++模板之声明定义分离编译模型
- C++模板应用——模板定义和实现分离
- C++模板函数声明定义分离编译错误详解
- c++模板函数声明定义分离编译错误详解
- c++模板定义和实现分离
- c++模板之声明定义分离编译模型
- C++模版函数声明和定义分离导致的错误
- c++模板函数声明定义分离编译错误详解
- c++模板函数声明定义分离编译错误详解