C++学习笔记(二十九) 虚析构函数

虚析构函数是为了解决这样的一个问题:基类的指针指向派生类对象,并用基类的指针删除派生类对象


无故的声明虚析构函数和永远不去声明一样是错误的。实际上,很多人这样总结:当且仅当类里包含至少一个虚函数的时候才去声明虚析构函数。

class A

{

...

virtual func();

};

class B:public A{};


A* p = new B;

delete p;

如果A的析构没有声明为虚函数,则调用的是:

A构造 

B构造

A析构


但如果A的析构声明为了虚函数,由于虚函数具有继承性,B的也是虚函数

则会根据指针指向的实际类型来调用函数

A构造

B构造

B析构

A析构


区别就在这里



#include <iostream>
using namespace std;
class Animal
{
public:
	Animal(){eat();} //在构造函数中不能通过虚函数调用子类函数 因为子类还没构造,析构也一样
	virtual ~Animal(){shout();} // 为了让delete p时 析构子类 所以设置为虚函数
	void play() //在普通函数中调用虚函数
	{
		eat();
		shout();
		sleep();
	}
	virtual void eat() {cout << "吃" << endl;}
	virtual void shout() {cout << "叫" << endl; }
	virtual void sleep() {cout << "睡" << endl;}
};

class Horse:public Animal
{
	//当将基类中的某一成员函数声明为虚函数后,派生类中的同名函数自动成为虚函数。
	//访问权限也是和父类中相同的  public 和 virtual 都是可写可不写的
public:
	Horse(){cout << "一匹马" <<endl; }
	~Horse(){cout << "马死了" <<endl;}
	virtual void eat() {cout << "吃草" << endl;}
	virtual void shout() {cout << "嘶~" <<endl;}
	virtual void sleep() {cout << " 站着睡" <<endl;}
};

class Tiger:public Animal
{
public:
	Tiger(){cout << "一只老虎"<<endl;}
	~Tiger() {cout<< "死老虎" <<endl;}
	virtual void eat() {cout << "吃肉" << endl;}
	virtual void shout() {cout << "吼~" <<endl;}
	virtual void sleep() {cout << "趴着睡" <<endl;}
};


int main()
{
	Animal *p = NULL;
	char  n;
	cout << "输入选项 h--马 t--老虎" <<endl;
	cin >> n;
	if(n == 'h')
		p = new Horse;
	else
		p = new Tiger;
	
	p->play();
	
	
	//只有在父类指针指向子类对象,delete时虚析构才起作用
	delete p; //需要将p的析构设置为虚函数 才可以调用子类的虚函数
}


/*输入选项 h--马 t--老虎
t
吃  //子类构造函数执行前先调用父类构造函数,子类没构造,所以构造函数中没有多态
一只老虎 //子类构造函数
吃肉  //多态
吼~ //多态
趴着睡 //多态
死老虎 //delete p p是Animal型的 所以会调用~Animal() 但要是想调用子类的 析构必须设置为虚的
叫 //析构函数中也没有多态 子类先析构,等到调用父类析构时 子类已经析构完了

 

* */


你可能感兴趣的:(C++学习笔记(二十九) 虚析构函数)