首页 > 解决方案 > 模板类实例化如何与类继承一起工作?

问题描述

代码

我有以下 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片段,我有以下警告:

  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(见上文)?

标签: c++

解决方案


我假设,你正在用 CLang 编译你的代码?(据我所知,这是 CLang 警告,除非 g++ 也开始发出它)。

无论如何,所问问题的答案(我只需要假设 OP 理解其他所有内容)是一个简单的事实template class DirectiveHandler<double>;- 这是隐式模板实例化定义,它会产生vtbls 等。(为 file 发出警告的事实实际上.cpp可能是一个错误,但 OP 并没有询问它)。

另一方面,extern template class DirectiveHandler<double>;不是一个定义。这是一个声明,它本身不会触发vptr's generation - 因此你看不到任何警告。


推荐阅读