【问题标题】:Can we perform deleting object through a pointer to one of its base classes? [duplicate]我们可以通过指向其基类之一的指针来执行删除对象吗? [复制]
【发布时间】:2015-05-01 13:17:59
【问题描述】:

如果我们定义一个虚拟析构函数会导致UB吗?例如:

struct A{ virtual ~A(){ } };

struct B : A { };

A *a = new B;


int main()
{
    delete a; //UB?
}

coliru

【问题讨论】:

  • 完全可以。这就是多态性的意义所在。 (但确实,请确保析构函数是虚拟的。)
  • @AlexD 为什么析构函数的虚拟性在这里很重要?我知道如果我们不声明析构函数,我们会得到 UB。

标签: c++ language-lawyer undefined-behavior


【解决方案1】:

很好正是因为析构函数是virtual——否则它会是UB。

也就是说,如果你想通过基类型的指针来删除派生类型的对象,那么基类的析构函数必须是virtual,否则就是UB。这样可以确保调用正确的析构函数(即派生的析构函数)——这就是所谓的运行时多态性。

【讨论】:

    【解决方案2】:

    “如果我们定义一个虚析构函数会导致UB吗?”

    不,这很好,因为析构函数被声明为virtual。加紧vtable 并首先调用~B 将由delete 处理。

    【讨论】:

    • 但实际上虚拟析构函数给了我们哪些非虚拟没有的?
    • @St.Antario “但实际上虚拟析构函数给了我们什么......”它确保你有一个vtable,它可以实现delete的行为.
    • 如果我们声明任何其他函数是虚拟的,而不是析构函数,我们将拥有 vtable。这也使得类具有多态性。
    • @St.Antario 好吧,这种机制 (vtable) 仍然只适用于其中的功能。如果不声明析构函数virtual,则无法从vtable 解析任何覆盖。
    【解决方案3】:

    没关系,只要析构函数是virtual

    如果析构函数不是,它就不会知道删除子类的成员。

    【讨论】:

      猜你喜欢
      • 2012-02-05
      • 1970-01-01
      • 2015-07-02
      • 1970-01-01
      • 1970-01-01
      • 2015-02-16
      • 2020-08-24
      • 1970-01-01
      • 2012-01-18
      相关资源
      最近更新 更多