【问题标题】:How to link against an overloaded template method如何链接一个重载的模板方法
【发布时间】:2016-10-10 09:53:27
【问题描述】:

下面的代码出现以下链接器错误:

undefined reference toIBase::Name() const'`

注意在 Base 类中,它调用了虚函数 Name()。目的是调用 Derived 类的 Name 实现,但链接器正在寻找 IBase::Name,而不是 Derived::Name()。如何解决?

template<class T_Extendable>
class IBase
{
public:
    virtual ~IBase() = default;
    virtual const std::string& Name() const = 0;
};

template<class T_Extendable>
class Base : public IBase<T_Extendable>
{
public:
    virtual ~Base() { "Destructing " << Name(); } // use virtual function Name()
};

class Derived : public Base<Foo>
{
public:
    virtual ~Derived() = default;
    const std::string& Name() const final { return "Derived"; } // implement pure virtual method IBase::Name()
};

【问题讨论】:

  • const std::string&amp; Name() const final { return "Derived"; } 是灾难的根源。你的编译器应该警告你返回一个临时的引用,看看这意味着什么。
  • 一定喜欢stackoverflow!当然,这看起来不像我们的生产代码,这是为了传达问题而提炼出来的。不过,我认为 Smeeheey 正在做某事。

标签: c++ templates


【解决方案1】:

您正在从析构函数中调用虚函数。根据标准的对象生命周期规则,这意味着即使被销毁的对象是 Derived,当 Base 析构函数运行时,它不再可以访问最派生类型(在本例中为 Derived 's) 虚函数覆盖。因此,它会尝试调用在IBase 中声明的版本,该版本未定义,因此您会收到链接器错误。

注意:这是指定此行为的标准的相关部分 [class.cdtor]:

可以调用4个成员函数,包括虚函数(10.3) 在建造或销毁期间 (12.6.2)。当一个虚函数 从构造函数或从 析构函数,包括在构造或销毁 类的非静态数据成员,以及调用的对象 apply 是正在构造或销毁的对象(称为 x), 调用的函数是构造函数或 析构函数的类,而不是在派生更多的类中覆盖它

【讨论】:

  • 太棒了!谢谢 Smeeheey,这也太幸运了,因为我们的 Base 类有几个虚方法,为了方便起见调用 Name(),我选择使用析构函数来展示用法,我们实际上在日志中的代码中这样做信息。我们在注释掉调用时链接很好,这当然是有道理的,派生的在基类被调用时已经被破坏了。
猜你喜欢
  • 1970-01-01
  • 2018-03-25
  • 1970-01-01
  • 2020-05-05
  • 2022-01-01
  • 1970-01-01
  • 2018-04-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多