1、首先,明确概念:
静态类型:对象被定义的类型,编译期确定;
动态类型:指针或引用所指向的对象的类型,运行期确定;
静态绑定:绑定的是静态类型;
动态绑定:绑定的是动态类型。
2、一些共识:非虚函数都是静态绑定的,虚函数都是动态绑定的;
基类的析构函数要设为虚函数。
3、静态绑定、动态绑定、虚析构函数是有一定的关系的:
class A{
public:
/*virtual*/ void func(){
std::cout << "A " << std::endl;
}
};
class B :public A{
public:
void func(){
std::cout << "B " << std::endl;
}
};
如果基类A中的func()函数为非虚函数,那么下面的程序
int main(){
A *p = new B();//p的静态类型为A,动态类型为B
B *p1 = new B();//p1的静态类型、动态类型都是B
B *p2 = nullptr;
p->func();//输出:A
p1->func();//输出:B
p2->func();//输出:B
delete p;
p = nullptr;
delete p1;
p1 = nullptr;
delete p2;
p2 = nullptr;
return 0;
}
如果把注释去掉,则结果为B,B, ,触发了动态绑定。
4、虚析构函数:由此可以看出,如果基类析构函数设置为非虚析构函数,那么当要删除基类指针指向的派生类对象时,会调用基类的析构函数而不会调用派生类的析构函数,从而导致派生类资源发生内存泄漏。