【问题标题】:virtual destructors in non-polymorphic and non-abstract base class非多态和非抽象基类中的虚拟析构函数
【发布时间】:2014-02-23 15:42:34
【问题描述】:

如果有人问过这个问题,我深表歉意。我正在编写一个将与 python 交互的 c++ 类。到目前为止的类实现是:

struct body_data
{
map <int, atom*> atoms;
map <int, bond*> bonds;
map <int, dihedral*> dihedrals;
};

这个类是另一个类的基类。我没有为这个类添加析构函数,因为我很困惑。在我读过的所有关于基类的析构函数的帖子中,他们建议析构函数应该是公共虚拟的或受保护的。由于我不打算在 c++ 代码或 python 接口中多态地使用上述类,我真的需要将析构函数设为公共虚拟或受保护吗?我正在考虑将这个类公开,这样程序员就知道永远不要多态地使用这个类。我的想法对吗?

【问题讨论】:

  • 创建 3 个类。上面有一个受保护的析构函数,一个从上面继承并且没有其他更改(但不是继承自)的类,以及从上面继承并做其他事情的第三个类。这意味着如果有人删除一个指向基址的指针,他们会得到一个错误:这很好,因为有两个不同的类是指向基址的有效指针,而错误地删除它们是未定义的行为。

标签: python c++ destructor


【解决方案1】:

当你有虚函数时,你只需要一个公共析构函数被声明为虚函数,表明你打算从你的类型派生。我强调“需要”,因为仅当您的基本类型具有非 POD 类型时才需要它您知道从您的类型派生的类型将具有非 POD 类型。是的,您可以拥有一个具有零虚拟成员的基类,但这样的基类将具有边际效用。不必要地添加虚拟成员会增加开销。即,如果您的类型除了虚拟析构函数之外没有虚拟成员,通常您已经将每个实例的大小增加了一个指针,并且所述对象的销毁会稍微慢一些,因为您必须至少调用析构函数单个内存间接。在第一个之后增量添加虚拟成员应该具有固定的内存成本,但您仍然会因不必要的虚拟化函数而受到运行时惩罚。

在您的情况下,您的数据类型似乎表明动态分配的内存(其值为原始指针的映射)的所有权,并且您已经表明这是为了作为其他类型的基础(这是关键),其中在这种情况下,您肯定想要定义一个正确释放内存的析构函数,并且由于您已经声明它是其他类型的基础,因此应该将其标记为虚拟,除非您可以绝对确保实例永远不会被任何东西破坏除了指向最派生类型的指针(做出这种假设非常危险,失败可能导致难以诊断内存泄漏)。

【讨论】:

  • 我正在用 c++ 编写代码,而不是使用 cython 将代码编译成 python 模块。如果 c++ 和 cython 代码始终使用派生类型,这是代码当前的发展方向。我可以假设 python 用户无法使用基指针访问派生类型吗?
  • 我使用它作为基类的原因是因为我有大约 3 到 4 个派生类,它们都使用 body_data 类中的成员。
  • @ZacharyKraus,仅仅因为他们使用 body_data 类并不意味着他们应该从它派生。你有没有想过让它成为每个人的成员?
  • 我确实想过让它们成为成员而不是使用继承。但是由于我最初对派生类进行编码的方式,我不得不更改我已经调试过的大部分代码,而不是再次调试它。
  • 最初我在我的一个派生类中拥有 body_data 类中的成员,并假设这些成员是该类的一部分,编写了大量代码。在测试和规划其余代码期间,我意识到,继承将是一个快速修复。具有讽刺意味的是,这是最好的解决方案,因为我需要适用于 body_data 而不是父类的方法。
猜你喜欢
  • 2019-04-20
  • 2011-03-21
  • 2013-11-03
  • 2014-05-17
  • 2013-11-01
  • 1970-01-01
  • 2016-01-16
  • 2015-06-04
  • 2019-12-08
相关资源
最近更新 更多