当前位置: 首页 > 知识库问答 >
问题:

哪个基类的虚析构函数在派生类中被重写

佴英奕
2023-03-14

当派生类不是立即派生,而是从已经派生的类派生时,我对覆盖函数感到困惑。

#include <iostream>

struct Base
{ 
    virtual ~Base() { std::cout << "Base destructor called\n"; }
};

struct Derived : Base
{
    Derived() {}
    // Implicitly supplied destructor, I'm guessing. Which is also virtual?
};

struct MostDerived : Derived
{
    MostDerived(){};
    ~MostDerived() { std::cout << "MostDerived destructor called\n"; }
};

int main()
{
    Derived* d = new MostDerived();
    delete d;
    Base* b = new MostDerived();
    delete b;
}

在这两种情况下,都调用了最派生的析构函数。我想知道是否只需要大多数基类有一个声明为虚拟的析构函数,在这种情况下,从它继承的所有其他类都有虚拟析构函数,覆盖上游的所有其他析构函数,如果你明白我的意思的话。

我不确定我是否有意义,基本上,如果我有一系列10个类,每个类都从上一个继承,那么链中的任何析构函数都会覆盖所有比它更基础的析构函数?

struct GreatGrandfather{~virtual GreatGrandfather(){}}; // Only this is necessary
struct Grandfather : GreatGrandfather {};
struct Father : Grandfather{};
struct Son : Father{};
struct Grandson : Son {};
struct GreatGrandson : Grandson{};

孙子的析构函数将覆盖其上面的所有类,但不会覆盖曾孙的析构函数?

而且,一旦基类的析构函数或其他函数被声明为虚拟,它的后代就不需要再次声明为虚拟了吗?

共有2个答案

汪建白
2023-03-14

析构函数重写基类的所有虚拟析构函数,包括间接基。此外,重写虚拟函数的函数本身也是虚拟的。因此,是的,Derived的隐式定义的析构函数是虚拟的,并且~Base~~ Derived都被~ MostDerived覆盖。当使用指向基类的指针销毁派生类类型的对象时,需要虚拟的析构函数就是基类的析构器。(然后派生类中的一个将隐式虚拟。)

漆雕原
2023-03-14

链中的任何析构函数都会覆盖比它更基础的所有析构函数?

是的,差不多。如果你不写析构函数,析构函数将由实现隐式提供。所以它也会隐式覆盖基类d'tor。

孙子的析构函数将覆盖其上面的所有类,但不会覆盖曾孙的析构函数?

它将覆盖< code >儿子的博士。它通过扩展覆盖< code >父亲的,以此类推。所以是的。它不能覆盖< code >曾孙,因为从它的定义来看,它不能预见未来,也不知道< code >曾孙会存在。

而且,一旦基类的析构函数或其他函数被声明为虚拟,那么它的后代都不需要再次声明为虚拟?

是的,与任何虚函数相同。一旦声明为虚拟,它在任何派生类中始终是虚拟的。

 类似资料:
  • 和构造函数类似,析构函数也不能被继承。与构造函数不同的是,在派生类的析构函数中不用显式地调用基类的析构函数,因为每个类只有一个析构函数,编译器知道如何选择,无需程序员干涉。 另外析构函数的执行顺序和构造函数的执行顺序也刚好相反: 创建派生类对象时,构造函数的执行顺序和继承顺序相同,即先执行基类构造函数,再执行派生类构造函数。 而销毁派生类对象时,析构函数的执行顺序和继承顺序相反,即先执行派生类析构

  • 我最近在读虚函数和虚析构函数,下面的问题引起了我的兴趣。 例如,我有以下继承链。 我知道基类的虚函数在派生类中默认是隐式虚的。所以,我认为这同样适用于析构函数。 我想知道,派生类的析构函数是否默认是虚拟的。如果没有,如果您提供一些解释,我将很高兴。

  • 主要内容:构造函数的调用顺序,基类构造函数调用规则前面我们说基类的成员函数可以被继承,可以通过派生类的对象访问,但这仅仅指的是普通的成员函数, 类的构造函数不能被继承。构造函数不能被继承是有道理的,因为即使继承了,它的名字和派生类的名字也不一样,不能成为派生类的构造函数,当然更不能成为普通的成员函数。 在设计派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数完成,但是大部分基类都有 private 属性的成员变量,它们在派生类中无法

  • C核心指南包含以下关于、和说明符的建议,特别是与派生类析构函数相关的建议: 如果基类析构函数声明为虚拟,则应避免将派生类析构函数声明为虚拟或重写。某些代码库和工具可能会坚持重写析构函数,但这不是这些准则的建议。 果然,是违反建议的工具之一。如果我没有指定或,运行会发出以下警告: 或者,如果仅指定为: 特别是,指定<code>override</code>的优点是(至少)确保正确地将基类析构函数指定

  • 由于派生类继承了其基类的成员,所以在建立派生类的实例对象时,必须调用基类的构造函数来初始化派生类对象的基类成员。派生类的构造函数既可以隐式调用基类的构造函数,也可以在派生类的构造函数中通过给基类提供初始化值(利用了前面所讲过的成员初始化值语法)显式地调用基类的构造函数。 派生类不继承基类的构造函数和赋值运算符,但是派生类的构造函数和赋值运算符能调用基类的构造函数和赋值运算符。 派生类的构造函数总是

  • 为什么一个虚函数在派生类中默认是虚的,甚至不可能在派生类中完全移除虚性,这有什么好的理由吗? 我希望这种行为的原因与我不希望默认情况下每个函数都是的原因相同。编译器可能会生成牺牲性能的vtables。 基类应该有一个vtable(我想要多态性在那里),但派生类没有vtable(我不希望多态性在那里,为什么我要那样,只是因为它派生了一个具有多态性的类?)。 我想解决的问题是更好地理解虚函数。我只是没