C++析构函数加上virtual是为了防止内存泄漏。
用在C++实现多态的时候,其基类要加virtual。
原因跟动态绑定有关,大家都知道,多态是通过虚函数实现的,而虚函数又是通过动态绑定实现的。
先举个例子:
-
class Base
-
{
-
public:
-
virtual void function()
-
{
-
cout<<"this is Base's function"<<endl;
扫描二维码关注公众号,回复: 3602927 查看本文章 -
}
-
virtual ~Base()
-
{
-
cout<<"this is Base's destroy"<<endl;
-
}
-
};
-
class Derived:public Base
-
{
-
public:
-
void function()
-
{
-
cout<<"this is Derived's function"<<endl;
-
}
-
~Derived()
-
{
-
cout<<"this is Derived's destroy"<<endl;
-
}
-
};
-
int main()
-
{
-
Base *ptr = new Derived();
-
ptr->function();
-
delete ptr;
-
return 0;
-
}
上面的代码,我先写了虚函数function,第31行就是动态绑定,而33行delete删除的是Base型基类指针,此指针是没有派生类Derived的析构函数的,所以如果不在基类的析构函数加上virtual的话,就不能动态绑定派生类的析构函数(当然析构函数的动态绑定你可以看出来跟一般函数的动态绑定相比是特殊的,析构函数的虚函数不用按照函数名来找对应的的函数)。一句话:基类的析构函数加了virtual就可以动态绑定派生类的析构函数,这样的话,在执行多态后删除其对象,就可以在删除对象的时候执行派生类的析构函数了(当然执行基类的析构函数是一定会的)。否则不会执行派生类的析构函数。
代码输出结果:
this is Derived's function
this is Derived's destroy
this is Base's destroy
你可以尝试一下把基类的析构函数前的virtual删掉(第9行),输出结果将是:
this is Derived's function
this is Base's destroy
一、构造函数
1.构造函数任何时候都不可以声明为虚函数,原因如下:1)虚函数的调用军需通过虚函数表vtable来调用,虚函数表是存储在内存空间的,在调用构造函数前,对象还未被实力化,也就没有该对象的内存空间,也无法找到虚函数表;2)虚函数表实在对象构造之后才建立的,所以构造函数不可能是函数。
2.不能在构造函数内调用虚函数,原因如下:假设有个class继承体系,如下代码,在该base class 的构造函数中调用虚函数,
class A{
public:
A();
virtual void print() const = 0;
.......
};
A::A(){
.......
print();
}
class B : public A{
public:
B();
virtual void print() const;
......
};
int main(){
B b;
}
当构造B的对象时,B的base class 成分肯定会在derived class 构造之前先构造,神奇的是此时A的构造函数调用的print()为A类内版本,因为base class构造期间,virtual函数绝不会下降到derived class阶层,因为base class构造期间,derived class成员变量尚未初始化。
二、析构函数
1.类的设计目的如果不是作为base class使用,或不是为了具备多态性,析构函数就不该声明为虚函数,原因如下:因为有虚函数的类就会有虚函数表存在,故对象体积会变大,同样因为虚表指针的存在,使得C++中类的对象不在和其他语言(如C)内的相同声明有着一样的结构,,因此也就不再可能把它传递至或接受其它语言所写的函数,故不在有移植性(除非你名确补偿vptr)。
带多态性质的base class或类中带有任何virtual函数,就一定要拥有一个virtual析构函数,原因如下:假设derived class对象经由base class指针被删除,而该base class带着一个non-virtual析构函数,实际执行时通常会发生对象的derived成分没有被销毁。
2.不能在析构函数内调用虚函数,原因如下:一旦derived class析构函数开始执行,对象的derived class成员就会呈现未定义值,所以C++ 就会视它仿佛不存在,进入base class析构后,对象就成为一个base class对象,而virtual函数和 dynamic_casts也这么认为,这也就失去了它动态调用的意义了。
--------------------- 作者:Su_720 来源:CSDN 原文:https://blog.csdn.net/luoxue720/article/details/75093855?utm_source=copy 版权声明:本文为博主原创文章,转载请附上博文链接!