模板类实例化如何与类继承协同工作

How does template class instantiation work together with class inheritance?

本文关键字:继承 协同工作 实例化      更新时间:2023-10-16

代码

我有以下两个类的片段,它们有一个单独的源文件和头文件。派生类是一个模板类。

handler.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; };

main.cpp

#include "handler.h"
template class DirectiveHandler<double>;    //explicit template instantiation
int main(int argc, char *argv[]){
....

据我所知,我需要在定义模板后实例化它,这可以隐式发生(省略template class DirectiveHandler<double>;),也可以显式发生。我假设由于源文件和头文件中的定义和声明分离,隐式实例化失败。

对于上面main.cpp的片段,我有以下警告:

  1. warning: explicit template instantiation DirectiveHandler<double> will emit a vtable in every translation unit

  2. 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>;-这是一个隐含的模板实例化定义,它产生了vtbls等等。(为.cpp文件发出警告的事实实际上可能是一个错误,但OP并没有对此进行询问)。

另一方面,extern template class DirectiveHandler<double>;不是一个定义。它是一个声明,本身不会触发vptr的生成,因此您不会看到任何警告。