构造函数是不能为虚函数的,但析构函数能够且常常必须是虚的。
构造函数,先调用基类的构造函数,其次调用更晚的派生类的构造函数。
析构函数和构造函数的顺序相反。
#include<iostream>
using namespace std;
class Base1
{
public:
~Base1(){
cout<<"~Base1()\n";
}
};
class Derived1:public Base1
{
public:
~Derived1(){
cout<<"~ Derived1"<<endl;
}
};
class Base2
{
public:
virtual ~Base2(){
cout<<"~Base2()\n";
}
};
class Derived2:public Base2
{
public:
~Derived2(){
cout<<"~ Derived2"<<endl;
}
};
int main()
{
Base1* bp = new Derived1;
delete bp;
Base2* bp2 =new Derived2;
delete bp2;
}
~Base1()
~ Derived2
~Base2()
delete bp只调用基类的析构函数 。
delete bp2 调用了派生类的析构函数。
析构函数是虚函数,可以避免内存泄漏的问题。
纯虚析构函数
纯虚构函数必须是合法的,且在实用时,有一个限制,必须为纯虚函数提供一个函数体。
为什么?析构函数总要按顺序进行调用,如果没有实体,调用什么呢?
纯虚构函数和虚构函数的区别是什么:
纯虚构函数使基类是抽象类,抽象类,不可以创建对象。
从某个含有虚析构函数的类中,继承一个类,不向其它纯虚函数,我们不要求在派生类中提供纯虚函数的定义。因为编译器会自动生成虚构函数。
#include<iostream>
using namespace std;
class Base
{
public:
virtual ~Base() = 0;
};
class Derive:public Base
{}
int main()
{
}
不会出现编译错误。
当我们类中,仅含有一个纯虚函数:
析构函数的纯虚性,唯一效果可以阻止基类的实例化。
如果有其他纯虚构函数将会执行这一操作,所以当虚析构函数是十分必要的,它是不是存虚的就没有那么重要。
#include<iostream>
using namespace std;
class Base
{
public:
virtual ~Base() = 0;
};
Base::~Base()
{
cout<<"~ Base"<<endl;
}
class Derive:public Base
{};
int main()
{
Base *p = new Derive;
delete p;
}
~ Base
可以看到,基类的纯虚构函数会被调用。
作为一个准则,任何时候,我们的类中,都要有一个虚函数,我们应当增加一个虚析构函数,即使我们什么都不做。
析构函数的虚机制
using namespace std;
class Base
{
public:
virtual ~Base();
virtual void f(){
cout<<"Base f function\n";
}
};
Base::~Base()
{
cout<<"~ Base"<<endl;
f();
}
class Derive:public Base
{
public:
~Derive(){
cout<<"~ Derive"<<endl;
};
void f(){
cout<<"Derive f function\n";
}
};
int main()
{
Base *p = new Derive;
delete p;
}
~ Derive
~ Base
Base f functio
在虚析构函数中调用函数,无论被调用的函数是否是虚析构函数,调用的都是本地的函数。
向下类型转换
#include<iostream>
using namespace std;
class Base
{
public:
virtual ~Base(){}
};
class Derive:public Base
{
public:
~Derive(){
};
};
class Derive2:public Base
{
public:
~Derive2(){
};
};
int main()
{
Base *p = new Derive;
Derive *pD = dynamic_cast<Derive *>(p);
Derive2 *pD2 = dynamic_cast<Derive2 *>(p);
cout<<"pD = "<<(long)pD<<endl;
cout<<"pD2 = "<<(long)pD2<<endl;
}
pD = 27020320
pD2 = 0
#include<iostream>
using namespace std;
class Base
{
public:
virtual ~Base(){}
};
class Derive:public Base
{
public:
~Derive(){
};
};
class Derive2:public Base
{
public:
~Derive2(){
};
};
int main()
{
Base *p = new Derive;
Derive *pD = dynamic_cast<Derive *>(p);
Derive2 *pD2 = dynamic_cast<Derive2 *>(p);
cout<<"pD = "<<(long)pD<<endl;
cout<<"pD2 = "<<(long)pD2<<endl;
//使用Dynamic 需要判空
Derive * pD3 = nullptr;
Derive2 * pD4 = nullptr;
if(typeid(pD3) == typeid(p))
{
pD3 = static_cast<Derive*> p;
}
//使用static_cast 可以先判断typeid是否一致
}