【问题标题】:C++ virtuality by examplesC++ 虚拟性示例
【发布时间】:2013-10-04 06:14:49
【问题描述】:

我试图通过以下示例了解 C++ 中的破坏行为: https://github.com/peterdemin/virtual-destruction-5-cents

该列表是否满足所有可能的流程? 应该添加什么? 如何将给定的示例转换为简短的术语?

https://stackoverflow.com/a/461224/135079 提出“当基类的析构函数要进行多态操作时,总是将它们设为虚拟。”这不包括场景 4。

Scott Meyers 的 Effective C++ 中的第 7 条状态:

  • 如果一个类有任何虚函数,它应该有一个虚析构函数;
  • 未设计为基类或未设计为多态使用的类不应声明虚拟析构函数。

这是轻的(应该不应该)并且面对场景2。

更新

我将6502提供的C++标准重写为伪代码:

if static type of object is different from its dynamic type:
    if the static type is a base class of the dynamic type:
        if the static type has a virtual destructor:
            We're fine - dynamic type's destructor will be called
        else:
            behavior is undefined [1]
    else:
        behavior is undefined [2]

[1] 代码将在没有警告的情况下编译,并且可能会正常工作,但不能保证并且可能会在运行时导致纠缠错误。

[2] 这很尴尬:

class A {};
class B {};
B *a = (B*)(new A());
delete a;

【问题讨论】:

  • 场景 4 永远不应该完成.. 您始终可以将“基”类的对象作为成员,而不是从它继承。场景2非常奇怪。也许它永远不应该这样设计。
  • 嗯,感谢您的设计说明。但我是在测试不同的虚函数组合是如何工作的,而不是设计概念。

标签: c++ virtual-destructor


【解决方案1】:

当您使用基指针销毁派生对象并且析构函数不是虚拟的时,您最终会陷入“未定义行为”场景。

N3690, 5.3.5 [expr.delete] - 3

在第一种选择(删除对象)中,如果是静态类型的 要删除的对象与其动态类型不同,静态 type 应该是对象的动态类型的基类 已删除且静态类型应具有虚拟析构函数或 行为未定义

github 存储库中给出的解释是完全错误的(“派生的析构函数没有被调用,但没有发生内存泄漏”)。你不能指望这一点。

我没有阅读其余部分,因为这会浪费时间。 UB 就是 UB……试图描述未定义是无稽之谈。

【讨论】:

  • 请添加一个链接,为什么它是未定义的行为。
  • @peterdemin:不幸的是,“官方”链接需要很多钱(很遗憾,C++ 标准不是免费的)。我添加了对我所知道的最后一个免费提供的草稿的引用。
  • 感谢更新。我在回答中改写了这条复杂的规则。似乎,就像它是通用的短期一样,我一直在寻找。
【解决方案2】:

当您将方法声明为虚拟时,这意味着您在指示编译器在处理派生类对象时应该始终搜索方法的派生版本。就这么简单。
在下面的示例中,如果您在基类方法中不使用 virtual 关键字,则会调用基类版本的方法。

#include <iostream>

class A
{
  public:
      virtual const char* fetchClassName() { return "A"; }
      // this is a virtual destructor:
      virtual ~A(){ cout<<"Destroying Base";}
  };

class B: public A
{
  public:
      virtual const char* fetchClassName() { return "B"; }
      virtual ~B(){ cout<<"Destroying Derive";}
};

int main(void)
{
   B obj_b;
   A &obj_a = obj_b;
   std::cout << obj_a.fetchClassName() << "\n";
}

【讨论】:

  • 此代码输出:B Destroying Derive Destroying Base。如果我在 ~A() 之前删除 virtual,结果保持不变。那么,你的意思是什么?
  • 有趣的事情发生了,当你不声明虚拟方法时:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-19
  • 1970-01-01
  • 2020-07-04
  • 2017-12-09
  • 1970-01-01
  • 1970-01-01
  • 2012-06-17
相关资源
最近更新 更多