explorer

万丈高楼平地起,勿在浮沙筑高台

0%

Effective C++ :为多态基类声明 virtual 析构函数

为保证多态析构的正确性,需要为基类的虚构函数加上virtual

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <string>

class BasicClass {
public:
virtual ~BasicClass() {
std::cout << "BasicClass destructor!\n";
}
};

class DerivedClass: public BasicClass {
public:
~DerivedClass() {
std::cout << "DerivedClass destructor!\n";
}
};

int main(void){

class BasicClass* p_class = new DerivedClass();

// 如果 BasicClass 的析构函数没有 virtual 关键字
// 那么执行 delete 后只会执行 BasicClass 的析构函数
// 也就是说,只释放了基类内存,而派生类的内存没有被释放掉
delete p_class;

return 0;
}

但这并不意味着每一个类的析构函数都需要为其加上virtual修饰,因为一旦加上,这个类所携带的信息就还得需要虚指针,虚指针指向对应的虚表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <string>

class BasicClass {
public:
virtual ~BasicClass() {
std::cout << "BasicClass destructor!\n";
}
private:
int val = 0;
};

class BasicClass2 {
public:
~BasicClass2() {
std::cout << "BasicClass2 destructor!\n";
}
private:
int val = 0;
};

int main(void) {

BasicClass basic_class;
BasicClass2 basic_class2;

std::cout << "sizeof BasicClass is " << sizeof(basic_class) << "\n";
std::cout << "sizeof BasicClass2 is " << sizeof(basic_class2) << "\n";

return 0;
}

输出:

1
2
3
4
sizeof BasicClass is 16
sizeof BasicClass2 is 4
BasicClass2 destructor!
BasicClass destructor!

所以:

  • 如果一个类不希望作为基类,那它需要使用final关键字来限定避免被继承。自然它也就不需要为析构函数加上virtual修饰了。
  • 如果一个类作为基类,需要应用多态的特性,就需要加上virtual修饰了。