在C++的多态中,为了晚绑定提出了虚函数和纯虚函数,利用父类指针管理子类对象来实现多态
由于子类对象在堆区开辟,在程序结束前需要手动管理父类指针,但是如果子类属性中有在堆区开辟的情况,这时候父类指针的管理不到了,在堆区的内存造成泄漏!
例如:
#include<iostream>
using namespace std;
class calculator
{
public:
virtual int getresult() = 0;
calculator()
{
cout << "父类构造" << endl;
}
~calculator()
{
cout << "父类析构" << endl;
}
public:
int n1;
int n2;
};
class add : public calculator
{
public:
add()
{
cout << "子类构造" << endl;
}
~add()
{
cout << "子类析构" << endl;
}
int getresult()
{
return n1 + n2;
}
};
int main()
{
calculator *cal = new add;
cal->n1 = 10;
cal->n2 = 20;
cout << cal->getresult() << endl;
delete cal;
}
最后的结果没有调用子类析构。
所以需要对析构函数进行特殊操作:将父类中的析构函数改为虚析构或纯虚析构。
#include<iostream>
using namespace std;
class Base
{
public:
Base()
{
cout << "父类构造" << endl;
}
virtual ~Base() = 0;//写成纯虚析构的形式,也可以虚析构
};
Base::~Base()
{
cout << "父类析构" << endl;
}
class son : public Base
{
public:
son(int a)
{
this->m_a = new int(a);
cout << "子类构造" << endl;
}
~son()
{
cout << "子类析构" << endl;
if(this->m_a!=nullptr)
{
delete m_a;
m_a =nullptr;
}
}
public:
int *m_a;
};
int main()
{
Base *s = new son(1);
delete s;
return 0;
}
笔记:
1.在多态中虚函数往往在父类中是没有任何意义的,主要任务是由子类来重写功能,所以可以改成纯虚函数的形式:
virtual 函数签名 =0;
一旦存在纯虚函数,这个类就被叫做抽象类,抽象类是无法实例化对象的。
2.如果父类是抽象类,子类继承父类而没有重写虚函数,也是抽象类,依旧不可以实例化对象。
3.当父类指针指向在堆区开辟的子类对象时,如果父类无虚析构,delete父类指针,子类析构都不会被调用;当父类有虚析构,delete父类指针,先析构子类,再析构父类。
4.也就是说,一旦子类中有指针属性,父类必须写虚析构或纯虚析构