c++ - 模板类实例化如何与类继承一起工作?
问题描述
代码
我有以下 2 个类的片段,它们具有单独的源文件和头文件。派生类是一个模板类。
处理程序.h
class BaseHandler {
public:
BaseHandler(){}
BaseHandler(const std::string& directive);
virtual ~BaseHandler();
virtual bool operator()();
private:
const std::string m_directive;
};
template<typename C>
class DirectiveHandler : public BaseHandler {
public:
DirectiveHandler(const std::string& directive);
~DirectiveHandler();
bool operator()() override;
private:
std::vector<C> m_configurations;
};
处理程序.cpp
#include "handler.h"
BaseHandler::BaseHandler(const std::string& directive) : m_directive(directive) {};
BaseHandler::~BaseHandler(){};
template<typename C>
DirectiveHandler<C>::DirectiveHandler(const std::string& directive) :
BaseHandler(directive) {};
template<typename C>
bool DirectiveHandler<C>::operator()(){ return true; };
主文件
#include "handler.h"
template class DirectiveHandler<double>; //explicit template instantiation
int main(int argc, char *argv[]){
....
据我了解,我需要在定义模板后对其进行实例化,这可以隐式(省略template class DirectiveHandler<double>;
)或显式发生。我假设由于各自的源文件和头文件中的定义和声明分离,隐式实例化失败。
使用上面的main.cpp片段,我有以下警告:
warning: explicit template instantiation DirectiveHandler<double> will emit a vtable in every translation unit
warning: instantiation of function DirectiveHandler<double>::operator() required here, but no definition available
如果更改template class DirectiveHandler<double>
为extern template class DirectiveHandler<double>;
两个警告消失。我明白为什么要清除警告 2,因为模板类位于handler.cpp中。我也看不到它是如何清除警告 1 的。
问题
为什么添加extern
关键字清除警告 1(见上文)?
解决方案
我假设,你正在用 CLang 编译你的代码?(据我所知,这是 CLang 警告,除非 g++ 也开始发出它)。
无论如何,所问问题的答案(我只需要假设 OP 理解其他所有内容)是一个简单的事实template class DirectiveHandler<double>;
- 这是隐式模板实例化定义,它会产生vtbl
s 等。(为 file 发出警告的事实实际上.cpp
可能是一个错误,但 OP 并没有询问它)。
另一方面,extern template class DirectiveHandler<double>;
不是一个定义。这是一个声明,它本身不会触发vptr
's generation - 因此你看不到任何警告。
推荐阅读
- windows - 如何在批处理文件中将选定的文件从一个文件夹复制到另一个文件夹?
- api - 从不受信任的服务访问外部 API
- amazon-web-services - 从 AWS ECR 存储库中获取特定标记的最新图像
- linux - 编译内核给出错误 No rule to make target 'debian/certs/debian-uefi-certs.pem'
- powershell-2.0 - Powershell 2.0 - Where-Object:无法绑定参数“FilterScript”
- mongodb - SpringBoot中mongoDB中如何构造要与$$ROOT合并的对象?
- bash - 将来自多个脚本的 bash 输出发送到单个文件
- haskell - 将函数带入作用域会使代码无法编译
- raspberry-pi - 我无法在树莓派 4 上获取 sonic pi
- c# - 如何将 ID 从“tr onclick”Url.Action 方法传递给控制器