【问题标题】:How does template class instantiation work together with class inheritance?模板类实例化如何与类继承一起工作?
【发布时间】:2019-06-05 13:42:27
【问题描述】:

代码

我有以下 2 个类的 sn-ps,带有单独的源文件和头文件。派生类是一个模板类。

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

handler.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&lt;double&gt;;)或显式发生。 我假设由于各自的源文件和头文件中的定义和声明分离,隐式实例化失败。

使用上面 main.cpp 的 sn-p 我有以下警告:

  1. warning: explicit template instantiation DirectiveHandler&lt;double&gt; will emit a vtable in every translation unit

  2. warning: instantiation of function DirectiveHandler&lt;double&gt;::operator() required here, but no definition available

如果将 template class DirectiveHandler&lt;double&gt; 更改为 extern template class DirectiveHandler&lt;double&gt;;,则两个警告都会消失。我明白为什么要清除警告 2,因为模板类位于 handler.cpp 中。我也看不到它是如何清除警告 1 的。

问题

为什么添加 extern 关键字会清除警告 1(见上文)?

【问题讨论】:

  • 因为现在你没有明确的模板实例化定义,只有声明。
  • @YSC,这个关闭肯定是不正确的。 OP在问一个完全不同的问题!我现在重新打开它。
  • @SergeyA 然而,CNR。这就是为什么我们要求minimal reproducible example
  • @YSC,首先,CNR 不同于副本。其次,您的复制尝试显然不正确 - OP 有多个文件和翻译单元,而您只有一个。我也有一种感觉 OP 正在使用 CLang,如果我是正确的,这是原始问题中缺少的一部分。
  • @YSC 什么? OP 询问为什么添加 extern 会删除警告。和dup有什么关系?我完全看不出你的推理。不幸的是,由于 OP 似乎对这个问题没有我那么感兴趣,所以我将避免进一步交谈,也不会对这个问题采取任何进一步的行动。

标签: c++


【解决方案1】:

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

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

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

【讨论】:

  • 我目前使用的是 qt creator (ide)。它使用 Clang 静态代码分析器,但代码是用 g++-6 编译的。我承认我并不完全理解将基类与模板派生类一起使用的所有细节。这确实回答了我的问题。
猜你喜欢
  • 2015-07-27
  • 2014-04-30
  • 1970-01-01
  • 1970-01-01
  • 2012-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多