例题
#include "bits/stdc++.h"
// 虚函数能在析构函数里面调用吗
class C {
public:
C() {
cout << "构造函数 C" << endl;
}
~C() {
cout << "析构函数 C" << endl;
}
};
class A {
public:
A() {
cout << "构造函数 A" << endl;
}
virtual void f() {
cout << "A::f" << endl;
}
~A() {
cout << "析构函数 A" << endl;
f();
}
};
class B :public A {
public:
C c;
B() {
cout << "构造函数 B" << endl;
}
void f() {
cout << "B::f" << endl;
}
~B() {
cout << "析构函数 B" << endl;
f();
}
};
int main() {
B *b = new B();
//A *a = new A();
delete b;
system("pause");
return 0;
}
运行结果
这里附带了一个问题 就是 析构函数可以调用虚函数吗?
答案是可以的!
那么调用的时会发生多态吗?
B *b = new B();
A *a = b;
delete a; // 调用什么?
或者
delete b; // 调用什么?
答案:
-
调用
delete a
只调用了 A的析构函数 以及 A::f
-
调用
delete b
调用了.
对于这部分我的理解:
- 析构函数不是Virtual的.不会发生多态. 只有虚函数才有可能发生多态.
同时构造函数和析构函数不能继承的.
所以声明是什么类型就调用哪个类型的析构函数.
小结
-
带有继承以及组合的类的构造函数顺序是: 父类的构造函数->组合成员对象的构造函数 ->子类自己的构造函数;
-
类成员变量的空间分配及初始化是在 调用自己构造函数之前 进行的,
他们的声明初始化顺序由声明顺序决定,这个点在构造函数的初始化列表中的面试考点经常考到,注意,不是由其出现在初始化列表中的顺序决定,而是由其在类中声明的顺序决定其初始化的顺序;
-
对象在析构的时候,析构函数的调用顺序与构造函数的执行顺序相反,这个很容易理解,因为常规创建对象比如ClassA a;是在栈里创建对象的,程序结束或离开了对象的作用域,自然要清空那个原来的栈,栈的弹出都是从栈顶里面一个个出栈的,但要注意通过new来创建的对象是在堆中创建的,所以对于new出来的对象是在delete的时候才会调用其析构函数,否则不会调用析构函数,即使其离开了作用域或者程序结束都不会调用其析构函数;