的 C++ 编译器都会保证在构造函数执行结束后,虚函数表指针肯定会被正确的初始化,在这之前,是没有保证的;
3,所以构造函数不可能成为虚函数,创建一个对象的时候,我们需要构造函数来初始化虚函数表的指针,因此构造函数相当于一个入口点,这个入口点负责虚函数调用的前期工作,这个入口点当然不可能是虚函数;
8,析构函数可以成为虚函数:
1,析构函数在对象销毁之前被调用,对象销毁之前意味着虚函数指针是正确的指向对应的虚函数表的;
2,建议在设计类时将析构函数声明为虚函数(工程中设计一个父类的析构函数为虚函数);
1,赋值兼容性申请子类对象给父类指针时,当 delete 作用在指针上时,编译器会直接根据指针类型(此时是父类)来调用相应的析构函数,若父类加上 virtual,编译器可以根据指针指向的实际对象(此时是子类)决定如何调用析构函数(多态);
9,构造、析构、虚函数编程实验:
1 #include <iostream>
2 #include <string>
3
4 using namespace std;
5
6 class Base
7 {
8 public:
9 Base() // 若申请为析构函数,则编译器在此处显示:error:constructors cannot be declared virtual.
10 {
11 cout << "Base()" << endl;
12 }
13
14 virtual void func()
15 {
16 cout << "Base::func()" << endl;
17 }
18
19 virtual ~Base() // 申请为虚函数时,编译器无显示
20 {
21 cout << "~Base()" << endl;
22 }
23 };
24
25
26 class Derived : public Base
27 {
28 public:
29 Derived()
30 {
31 cout << "Derived()" << endl;
32 }
33
34 virtual void func()
35 {
36 cout << "Derived::func()" << endl;
37 }
38
39 ~Derived()
40 {
41 cout << "~Derived()" << endl;
42 }
43 };
44
45 int main()
46 {
47 Base* p = new Derived();
48
49 // ...
50
51 delete p; // 期望调用完子类析构函数再调用父类的析构函数;但是如果父类没有申请为析构函数,则只调用父类析构函数;这是因为此时删除的是一个父类的指针,由于并没有将析构函数申请为 virtual,因此在这样情况下,编译器直接根据指针 p 的类型来决定调用哪一个构造函数,由于指针 p 的类型是父类的类型,所以编译器直接暴力认为调用父类构造函数就可以了;当将父类的虚函数声明为 virtual 时,编译器就不会简单的根据指针 p 的类型来简单调用父类的或者是子类的析构函数了,这个时候由于析构函数是虚函数,所以在执行这行代码的时候,编译器会根据指针 p 指向的实际对象来决定如何调用析构函数,这是多态;
52
53 return 0;
54 }
1,工程中设计一个类作为父类出现时,我们都要将析构函数声明为虚函数,否 则就有可能产生内存泄漏,因为有可能跳过子类析构函数的调用,如果子类 析构函数中有释放资源的操作(动态内存空间),则后果不堪设想;
10,构造函数中是否可以发生多态?析构函数中是否可以发生多态?
11,构造函数中(构造函数中调用虚函数)不可能发生多态行为:
1,在构造函数执行时,虚函数表指针未被正确初始化;
12,析构函数中(析构函数中调用虚函数)不可能发生多态行为:
1,在析构函数执行时,虚函数表指针可能已经被摧毁;
13,析构函数和构造函数中(调用虚函数时)不能发生多态行为,只调用当前类中的函数版本;
1,构造函数和析构函数中调用虚函数实验:
1 #include <iostream>
2 #include <string>
3
4 using namespace std;
5
6 class Base
7 {
8 public:
9 Base()
10 {
11 cout << "Base()" << endl;
12
13 func();
14 }
15
16 virtual void func()
17 {
18 cout << "Base::func()" << endl;
19 }
20
21 virtual ~Base()
22 {
23 func();
24
25 cout << "~Base()" << endl;
26 }
27 };
28
29
30 class Derived : public Base
31 {
32 public:
33 Derived()
34 {
35 cout << "Derived()" << endl;
36
37 func();
38 }
39
40 virtual void func()
41 {
42 cout << "Derived::func()" << endl;
43 }
44
45 ~Derived()
46 {
47 func();
48
49 cout << "~Derived()" << endl;
50 }
51 };
52
53
54 int main()
55 {
56 Base* p = new Derived(); // 打印 Base(),Base::func(),Derived(),Derived::func(),
57
58 // ...
59
60 delete p; // 打印 Derived::func(),