c++类模板为什么不能编译到动态库中来使用
在使用c++的时候,我们习惯于将类的定义声明在头文件中,即.h文件;将类函数的实现定义在源文件中,即.cpp文件。如果我们要提供的是一个动态库,那么这种方式更常用,使用动态库的时候,包含头文件,编译的时候链接动态库就可以了。
但是如果我们提供的是类模板,这种方式就不适用了,本文分析原因。
1模板类错误用法
如下是代码示例,t.h中声明了模板类Box,但是没有实现;t.cpp中实现了Box的每个函数。t.h和t.cpp通过命令g++ -fPIC --shared t.cpp -o libtemplate.so编译出动态库。main.cpp中使用了模板类,编译main.cpp的时候通过g++ main.cpp libtemplate.so链接动态库。
在编译的时候会报错,错误信息如下,提示没有Box<int>这个类,这是为什么呢?这是c++语言常用的使用方式啊,为什么编译会报错呢?
通过objdump -tT libtemplate.so查看动态库中的符号,发现动态库中没有模板类的任何信息,所以编译main的时候编译失败也可以解释了。但是,为什么动态库中没有模板类的任何信息呢,因为g++编译器在编译的时候只有遇到模板的实例,才会做真正的编译,如果只有一个模板,没有实例,编译器是不会编译的。
t.h
template <typename T>
class Box {
public:// 构造函数Box(T value);// 获取值T getValue() const;// 设置值void setValue(T value);private:T value_;
};
t.cpp
#include "t.h"template <typename T>
Box<T>::Box(T value) : value_{value} {}template <typename T>
T Box<T>::getValue() const {return value_;
}template <typename T>
void Box<T>::setValue(T value) {value_ = value;
}
main.cpp
#include "t.h"
#include <iostream>int main() {Box<int> b{100};std::cout << b.getValue() << std::endl;return 0;
}
2模板类正确用法
在使用类模板的时候,在编译的时候要能找到类的实现才可以,找不到的类的实现,那么实例化就无从谈起,所以会编译失败。
一般在使用类模板的时候,类的实现和声明要放在同一个文件中。