c++模板类的使用,编译的问题
1,模板类编译的问题
前两天在写代码时,把模板类的声明和分开放在两个文件中了,类似于下面这样:
stack.hpp:
#ifndef _STACK_HPP
#define _STACK_HPP
template <typename Type>
class stack {
public:
stack();
~stack();
};
#endif
stack.cpp:
#include <iostream>
#include "stack.hpp"
template <typename Type> stack<Type>::stack() {
std::cerr << "Hello, stack " << this << "!" << std::endl;
}
template <typename Type> stack<Type>::~stack() {
std::cerr << "Goodbye, stack " << this << "." << std::endl;
}
main.cpp
#include "stack.hpp"
int main() {
stack<int> s;
return 0;
}
编译
$ g++ -c -o main.o main.cpp
$ g++ -c -o stack.o stack.cpp
$ g++ -o main main.o stack.o
main.o: In function `main':
main.cpp:(.text+0xe): undefined reference to 'stack<int>::stack()'
main.cpp:(.text+0x1c): undefined reference to 'stack<int>::~stack()'
collect2: ld returned 1 exit status
make: *** [program] Error 1
提示找不到函数的定义
在网上寻找的答案如下:
It is not possible to write the implementation of a template class in a separate cpp file and compile. All the ways to do so, if anyone claims, are workarounds to mimic the usage of separate cpp file but practically if you intend to write a template class library and distribute it with header and lib files to hide the implementation, it is simply not possible.
To know why, let us look at the compilation process. The header files are never compiled. They are only preprocessed. The preprocessed code is then clubbed with the cpp file which is actually compiled. Now if the compiler has to generate the appropriate memory layout for the object it needs to know the data type of the template class.
Actually it must be understood that template class is not a class at all but a template for a class the declaration and definition of which is generated by the compiler at compile time after getting the information of the data type from the argument. As long as the memory layout cannot be created, the instructions for the method definition cannot be generated. Remember the first argument of the class method is the 'this' operator. All class methods are converted into individual methods with name mangling and the first parameter as the object which it operates on. The 'this' argument is which actually tells about size of the object which incase of template class is unavailable for the compiler unless the user instantiates the object with a valid type argument. In this case if you put the method definitions in a separate cpp file and try to compile it the object file itself will not be generated with the class information. The compilation will not fail, it would generate the object file but it won't generate any code for the template class in the object file. This is the reason why the linker is unable to find the symbols in the object files and the build fails.
Now what is the alternative to hide important implementation details? As we all know the main objective behind separating interface from implementation is hiding implementation details in binary form. This is where you must separate the data structures and algorithms. Your template classes must represent only data structures not the algorithms. This enables you to hide more valuable implementation details in separate non-templatized class libraries, the classes inside which would work on the template classes or just use them to hold data. The template class would actually contain less code to assign, get and set data. Rest of the work would be done by the algorithm classes.
具体原因就是:
模板类其实就不是一个类,c++的编译器在编译.cpp产生二进制目标文件的时候,需要根据函数的参数类型来确定链接符号(编译器不编译.h文件),而编译模板类的时候因为函数的参数类型都没有确定,所以也就不能产生链接符号,所以在编译阶段是不会报错的,但是在链接阶段就报错了。针对这种情况有三种解决办法,但是最优的还是把实现和声明都放在头文件中。如果不想让c++类显得臃肿,可以在类里面声明,在类外进行实现。
参考链接
https://www.zhihu.com/question/20630104
https://www.bbsmax.com/A/rV573nLE5P/
c++模板类的使用,编译的问题的更多相关文章
- C++ 中的模板类声明头文件和实现文件分离后,如何能实现正常编译?
C++ 中的模板类声明头文件和实现文件分离后,如何能实现正常编译? 这个feature叫做Export Template,即外名模板,它的作用在于使得模板代码可依照C/C++语言习惯,将模板声明和实现 ...
- c++模板类编译错误
最近想写一个c++模板类,实现一个有向图.依据惯例,类在头文件中声明,类的实现写在源文件中.可是编译的时候出现了如下错误: undefined reference to 通过谷歌发现,这是一个很常见的 ...
- C++基础 (9) 第九天 编译器对模板类的二次编译 类模板 自定义数组类
1 昨日回顾 2 编译器对于模板的二次编译 写一个模板函数 然后进行调用 g++ template.cpp -o template // 汇编 g++ -S template.cpp –o templ ...
- 关于g++编译模板类的问题
今天搞了我接近4个小时,代码没错,就是调试没有通过,无论怎么也没有想到是编译器的问题 g++不支持c++模板类 声明与实现分离,都要写到.h文件里面. 以后记住了.
- C++11模板类使用心得
1.推荐使用std::shared_ptr<TaskT>代替指针TaskT*使用,shared_ptr是一种智能指针,能自主销毁释放内存,在c++11中被引入,在多线程编程中有很大的用处, ...
- c++模板类
c++模板类 理解编译器的编译模板过程 如何组织编写模板程序 前言常遇到询问使用模板到底是否容易的问题,我的回答是:“模板的使用是容易的,但组织编写却不容易”.看看我们几乎每天都能遇到的模板类吧,如S ...
- C++ 模板函数与模板类
一.模板函数 函数模板提供了一类函数的抽象,即代表了一类函数.当函数模板被实例化后,它会生成具体的模板函数.例如下面便是一个函数模板:
- 模板类重载<<运算符
写了一个Matrix模板类,需要重载<<, 1.需要友元函数 2.需要此函数的实现在.h中(本人试验出来的,放在.cpp中编译不通过) template <typename T> ...
- C++模板类的使用
1.定义模板类 通过类似于下面的语法可以定义一个模板类: template<typename T> class Job : public virtual RefBase { public: ...
随机推荐
- 【Python】批量给图片增加水印工具
背景 最近有一些图片需要增加水印,找了一圈也没看见比较好的工具,又不想用破解的PS,干脆自己做了一个GUI工具,有需要的同学自取 功能 支持水印预览 自定义水印文字内容 支持行楷和微软雅黑两种字体 支 ...
- Codeforces 643G - Choosing Ads(线段树)
Codeforces 题目传送门 & 洛谷题目传送门 首先考虑 \(p>50\) 的时候怎么处理,也就是求一个区间的绝对众数.我们知道众数这个东西是不能用线段树直接维护的,因为对于区间 ...
- 关于 KB/KiB、MB/MiB
ermmm--怎么说呢,这个非常容易搞混,那就写篇 blog 澄清一下吧-- 首先贴上百度百科的官方定义 根据国际单位制标准,1KB = 1000B(字节, Byte). 根据按照 IEC 命名标准 ...
- R shinydashboard ——2. 结构
目录 1.Shiny和HTML 2.结构 3. 标题Header 4. 侧边栏Siderbar 5.主体/正文Body box tabBox infoBox valueBox Layouts 1.Sh ...
- GWAS在农业上应用
农业的组学技术应用虽然落后于人的研究,这是什么意义的问题,但有时农业基因组有自己无可比拟的优势,那就是材料.下面介绍GWAS应用. GWAS(Genome-wide association study ...
- 关于GCC编译
GCC参数详解 gcc是gnu compiler collection 的简称,他包含了多种语言的编译器,如C, C++, Objective-C, Objective-C++, Java, Fort ...
- 毕业设计之ansible_quan_bbs设置
ansible创建连接: 客户端(管理节点) 可能需要安装包: yum install -y libselinux-python 实现ssh免密码登陆管理的服务器 [apps@anza ~]$ sud ...
- abundant
In ecology [生态学], local abundance is the relative representation of a species in a particular ecosys ...
- Spark(二十一)【SparkSQL读取Kudu,写入Kafka】
目录 SparkSQL读取Kudu,写出到Kafka 1. pom.xml 依赖 2.将KafkaProducer利用lazy val的方式进行包装, 创建KafkaSink 3.利用广播变量,将Ka ...
- Spark(三)【RDD中的自定义排序】
在RDD中默认的算子sortBy,sortByKey只能真的值类型数据升序或者降序 现需要对自定义对象进行自定义排序. 一组Person对象 /** * Person 样例类 * @param nam ...