C++ 模板类实例化如何与类继承一起工作? 代码
我有以下两个类的片段,分别有一个源文件和头文件。派生类是一个模板类 handler.hC++ 模板类实例化如何与类继承一起工作? 代码,c++,C++,我有以下两个类的片段,分别有一个源文件和头文件。派生类是一个模板类 handler.h 类BaseHandler{ 公众: BaseHandler(){} BaseHandler(const std::string和directive); 虚拟~BaseHandler(); 虚拟布尔运算符(); 私人: const std::string m_指令; }; 模板 类DirectiveHandler:公共BaseHandler{ 公众: DirectiveHandler(const std::st
类BaseHandler{
公众:
BaseHandler(){}
BaseHandler(const std::string和directive);
虚拟~BaseHandler();
虚拟布尔运算符();
私人:
const std::string m_指令;
};
模板
类DirectiveHandler:公共BaseHandler{
公众:
DirectiveHandler(const std::string和directive);
~DirectiveHandler();
布尔运算符()()覆盖;
私人:
std::向量m_配置;
};
handler.cpp
#包括“handler.h”
BaseHandler::BaseHandler(const std::string&directive):m_指令(directive){};
BaseHandler::~BaseHandler(){};
模板
DirectiveHandler::DirectiveHandler(常量std::字符串和指令):
BaseHandler(指令){};
模板
bool DirectiveHandler::operator(){return true;};
main.cpp
#包括“handler.h”
模板类DirectiveHandler//显式模板实例化
int main(int argc,char*argv[]){
....
据我所知,我需要在定义模板后对其进行实例化,这可以是隐式的(省略模板类DirectiveHandler;
)也可以是显式的。
我假设隐式实例化失败是因为在相应的源文件和头文件中分离了定义和声明
对于上面main.cpp的代码段,我有以下警告:
警告:显式模板实例化DirectiveHandler将在每个翻译单元中发出vtable
警告:此处需要函数DirectiveHandler::operator()的实例化,但没有可用的定义
模板类DirectiveHandler
更改为外部模板类DirectiveHandler;
这两个警告都会消失。我确实理解为什么会清除警告2,因为模板类驻留在handler.cpp中。我看不出它是如何清除警告1的
问题:
为什么添加了
extern
关键字clear warning 1(参见上文)?我假设,您是在用叮当声编译代码?(据我所知,这是叮当声警告,除非g++也开始发出它)
无论如何,问题的答案(我只需假设OP了解其他一切)是一个简单的事实,template class DirectiveHandler;
——这是隐式模板实例化定义,它生成vtbl
s等等。(针对.cpp
文件发出警告的事实可能实际上是一个bug,但OP没有询问)
另一方面,
extern template class DirectiveHandler;
不是一个定义。它是一个声明,本身不会触发vptr
的生成,因此您看不到任何警告。因为现在您没有显式的模板实例化定义,只有声明。@YSC,这个闭包肯定是不正确的。OP是在问一个完全不同的问题!我现在重新打开了它。@SergeyA,但是,。这就是为什么我们要问一个。@YSC,首先,CNR不同于复制品。其次,你复制的尝试显然是不正确的-OP有多个文件和翻译单位,你只有一个。我也感觉OP在使用CLang,如果我正确的话t、 这是原始问题中缺少的一部分。@YSC what?OP询问为什么添加extern
会删除警告。这与dup有什么关系?我完全看不出你的推理。不幸的是,由于OP似乎对这个问题没有我感兴趣,我将不再继续对话,也不再采取任何进一步的行动我目前使用的是qt creator(ide)。它使用的是Clang静态代码分析器,但代码是用g++-6编译的。我承认我不完全理解将基类与模板派生类一起使用的所有细节。这确实回答了我的问题。
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;
};
#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[]){
....