【问题标题】:Can a base destructor really be overridden by a derived destructor in C++?基析构函数真的可以被 C++ 中的派生析构函数覆盖吗?
【发布时间】:2019-06-21 02:26:02
【问题描述】:

在整个网络上,以及在 Bjarne Stroustrup 的 C++ 书中,我都看到诸如“如果基析构函数被声明为虚拟,那么它会被派生类的析构函数覆盖”这样的语句。

但是,为什么它被称为覆盖?它与覆盖函数的“通常”方式略有不同吗?通常,我指的是派生类中的典型虚函数,与基类中的方法签名共享相同的方法签名。在这种通常情况下,根据指针指向的实际对象,无论是基础版本还是派生版本都将被忽略......让我们不要详细讨论通常意义上的覆盖如何工作。

但在析构函数的情况下,基础析构函数最终会被调用,无论如何。而且,它的名字也不同。为什么又叫覆盖呢?

【问题讨论】:

    标签: c++11 overriding virtual-destructor


    【解决方案1】:

    为什么又叫覆盖?

    因为它覆盖了基类的析构函数。

    考虑一下:

    struct Foo
    {
       ~Foo() {}
    };
    
    struct Bar : Foo
    {
       ~Bar() {} // This does not override ~Foo.
    };
    
    Foo* fptr = new Bar;
    delete fptr;  // ~Foo() is called.
    

    如果指针为Bar*,将调用~Bar()

    Bar* bptr = new Bar;
    delete bptr;  // ~Bar() is called.
    

    但是,如果您将 Foo 更改为:

    struct Foo
    {
       virtrual ~Foo() {}
    };
    
    struct Bar : Foo
    {
       ~Bar() {} // This overrides ~Foo.
    };
    

    然后使用

    Foo* fptr = new Bar;
    delete fptr;  // ~Bar() is called.
                  // ~Bar() overrides ~Foo().
    

    【讨论】:

    • 最后一种情况,我的看法和你的不一样。 ~Bar() 被调用,然后 ~Foo() 被调用。那是我的原点!为什么又叫覆盖?
    • @softwarelover,你说得对——首先调用~Bar(),然后在~Bar() 返回之前调用~Foo()~Bar() 仍然被称为重写析构函数,因为没有重写性质,delete fptr 最终不会调用 ~Bar()
    • 我明白了。事实上,~Foo() 是在 ~Bar() 中被调用的,这使得这种覆盖不同于通常的覆盖情况,其中函数是典型的虚函数而不是析构函数。不是吗?
    • @softwarelover,是的。构造函数和析构函数是特殊的函数,并且有自己的特点。
    猜你喜欢
    • 2014-05-17
    • 2014-08-08
    • 1970-01-01
    • 2011-12-13
    • 2015-06-28
    • 2014-01-09
    • 2015-04-16
    • 1970-01-01
    • 2020-01-16
    相关资源
    最近更新 更多