虚析构函数的作用是( C )?
A. 虚基类必须定义虚析构函数
B. 类对象作用域结束时释放资源
C. delete动态对象时释放资源
D. 无意义


在 C++ 中,虚析构函数的作用是允许通过基类指针删除派生类对象时,正确地调用派生类的析构函数(在运行时根据指针指向的实际类型先调用派生类的析构函数),以正确的释放派生类中的资源。

如果基类的析构函数不是虚函数,通过基类指针删除派生类对象时,只会根据指针类型调用基类的虚构函数,这在编译期就确定了,而不会调用派生类的析构函数,可能发生内存泄漏。

C++的多态和实现方式

关于选项 A,基类或虚基类并不一定要定义虚析构函数,只是通常情况下,我们将基类的析构函数声明为虚函数,以实现多态。但是,如果我们只需要继承,而不要实现多态,那虚基类的析构函数也可以不被定义为虚函数。

简单来说,(虚)基类不一定需要虚析构函数,只有这个类呈现出多态性质的情况下才需要定义虚析构函数。

关于选项 B,如果类对象是静态建立的,则类对象作用域结束时,由编译器调用类的析构函数释放该类对象的资源,但是这种情况下其实无法实现多态,因为通过虚函数实现的动态多态必须是基类函数指向派生类对象的,也就是说这个对象是被动态建立在堆上的,所以对静态建立的类,实际上不需要将析构函数定义为虚函数,这显然不是虚析构函数的作用;

另一种情况,如果类是(通过 new)被动态建立在堆上的,那也必须我们手动的使用 delete 来调用相应的析构函数来释放资源,而不会随着类对象作用域的结束而自动释放资源。

关于类的静态建立和动态建立

基类和虚基类

基类(Base Class)和虚基类(Virtual Base Class)是面向对象编程中的概念,用于描述类与类之间的继承关系。

基类(Base Class)

基类是用来派生其他类的类。它可以包含成员变量和成员函数,这些成员可以被派生类继承和使用。基类的成员可以分为共有 public 成员、保护 protected 成员和私有 private 成员,这些访问修饰符决定了派生类对基类成员的访问权限。派生类可以通过继承基类,获取基类的属性和方法,并且可以在派生类中添加自己的成员变量和成员函数,或者重定义基类的成员(如果需要实现多态,被重写的基类函数需要定义为虚函数)。

虚基类(Virtual Base Class)

虚基类是一种在多重继承中用来解决菱形继承(Diamond Inheritance)问题的机制。菱形继承问题发生在一个派生同时继承了同一个基类的不同路径的两个或多个派生类。这会导致派生类中出现多份同名基类成员的副本,从而可能引发二义性和资源浪费。

虚基类通过在基类继承声明中使用 virtual 关键字来定义。当一个类被声明为虚基类后,无论有多少派生类,它们共享一个相同的基类子对象。这意味着在派生类中,对虚基类的成员访问不会产生二义性,因为只有一份虚基类成员副本。

例如,考虑以下继承结构:

1
2
3
4
class A { ... };
class B : virtual public A { ... };
class C : virtual public A { ... };
class D : public B, public C { ... };

在上述例子中,B 和 C 都虚拟继承了 A,而 D 继承了 B 和 C,这样即使存在多个继承路径,D 中的虚基类 A 成员只有一份。

详细了解:虚继承和虚基类