【问题标题】:Inheritance from class with pure abstract destructor从具有纯抽象析构函数的类继承
【发布时间】:2016-03-01 02:12:06
【问题描述】:

如果父类有一个纯虚析构函数,我该如何正确继承它?我有一个头文件(由 IBM Rational Rose 生成),如下所示:

class MyClass{
protected:
  inline MyClass() {};
  MyClass(const MyClass&);
  MyClass& operator=(const MyClass&);
public:
  inline virtual ~MyClass() = 0;
  virtual void someMethod() = 0;
};

现在我想实现这个纯抽象类 - 即

class MyClassImpl : public MyClass {
public:
  MyClassImpl(){}
  virtual void someMethod() {}
};

int main(int argc, char*argv[]) {
  MyClassImpl impl;
  return 0;
}

但无论我尝试什么(即在 MyClassImpl 中定义析构函数;虚拟/非虚拟),我都会不断收到错误消息:error LNK2019: unresolved external symbol "public: virtual __thiscall MyClass::~MyClass(void)" (??1MyClass@@UAE@XZ) referenced in function "public: virtual __thiscall MyClassImpl::~MyClassImpl(void)" (??1MyClassImpl@@UAE@XZ)

有什么方法可以在不更改MyClass 的情况下实现MyClassImpl

【问题讨论】:

  • 你用的是什么编译器?看起来像 msvc 但只是为了确认。
  • 您不能销毁没有析构函数的类的实例。你只能动态创建一个然后泄漏它。
  • 因为 'MyClass::~MyClass( void )' 无法解析。在头文件或像 @MinorThreat 发布的单独文件中定义该方法。

标签: c++ inheritance abstract-class


【解决方案1】:

你必须定义析构函数,即使它是纯虚的(唯一的)。

添加

MyClass::~MyClass() {}

恰好在一个 .CPP 文件中。

(例如,参见“纯虚拟析构函数”下的 http://en.cppreference.com/w/cpp/language/destructor。还有 Why do we need a pure virtual destructor in C++?。)

【讨论】:

  • 普通成员函数可以做到这一点吗?
  • @CaptainGiraffe 是的。您可以定义任何纯虚函数,但只能通过非虚调用来调用它,例如base::foo().
【解决方案2】:

C++ 编译器在编译过程中添加了一些隐式自动生成的代码。

class MyClassImpl : public MyClass {
public:
  MyClassImpl(){}
  virtual void someMethod() {}

  // Begin autogenerated code
  virtual ~MyClassImpl() {
    MyClass::~MyClass(); // <- This will break because your parent class
                         // lacks any destructor body and linker will             
                         // report the missing symbol.
  }
  // End autogenerated code

};

幸运的是,您可以在任何 cpp 文件中定义析构函数体,而无需触及 Rational Rose 生成的文件。例如,您可以在 main() 函数附近添加此行。

MyClass::~MyClass(){} // Empty destructor

【讨论】:

  • 这也许可以解释问题,但并没有说明任何解决方案
【解决方案3】:

宁可像这样声明你的 virtual 析构函数,带有一个主体:

inline virtual ~MyClass() {};
inline virtual ~MyClass() = default; // C++11

它必须被实现(不仅仅是声明),否则,将无法破坏 MyClass 及其派生类(您的声明禁用默认生成的析构函数,但不提供替代实现)。

注意virtual成员函数仍然可以有一个实现,所以你可以有:

inline virtual ~MyClass() = 0;

virtual MyClass::~MyClass() {}; // defined in .h file because of inline

【讨论】:

  • = 0; 在 OP 的代码中,强制派生类覆盖析构函数。大概这是故意的(没有其他原因有人会这样做)。您的第一个建议会改变行为。 (另外,在你的前两行 inline 是多余的,提供正文内联意味着 inline
猜你喜欢
  • 2015-12-10
  • 2020-06-19
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 2013-01-03
  • 1970-01-01
  • 2011-11-17
  • 2019-04-20
相关资源
最近更新 更多