虚函数和多态性2——抽象基类和纯虚函数

1、概念

(1)抽象类:抽象类也是一种特殊的类,该类不能用来定义对象,这种类存在的作用只有一个,那就是被继承。它是为了避免实例化无意义的一些类,所以可以使用抽象类来实现,抽象类一般都是作为基类使用的,故称为抽象基类。抽象类可以看做是一个统一的接口,至于接口下面是怎么实现的,可以由派生类来完成,这样带来的好处就是可以使用接口与具体实现分离,使程序具有良好的可扩展性。

(2)纯虚函数:纯虚函数是一个特殊的函数,因为它与一般的函数不同,纯虚函数没有具体实现,换句话说,就是纯虚函数没有函数体的实现。


2、抽象类和纯虚函数的定义格式

(1)抽象类的定义:如果一个类中包含一个或者多个纯虚函数,就称为抽象类,而且抽象类必须作为基类才有意义,抽象类是不可以定义对象的。具体格式如下:
class <类名>

{

<访问权限>:

virtual <返回类型>   <函数名>(参数列表) =  0;

//其他纯虚函数

};


(2)纯虚函数的定义格式:

virtual <返回值类型><函数名>(参数列表)  =  0;      //注意纯虚函数必须在类体内进行定义

注:纯虚函数的作用是提供一个接口,告诉编译系统该函数的实现是在其派生类中,只有被继承才能调用该函数。


3、虚析构函数

(1)定义:虽然构造函数不能被定义为虚函数,但析构函数可以被定义为虚函数,定义虚析构函数只需要在该析构函数的前面加上virtual即可。


(2)优势:如果一个基类的析构函数定义为虚函数后,其派生类的析构函数也将被自动定义为虚函数。那么,在实际应用中,系统将采用动态绑定的机制调用相应的析构函数,使析构过程更加彻底。


4、实例分析

<pre name="code" class="cpp">/**************************************************
时间:2016年10月5日18:21:31
功能:区别有无虚析构函数的作用
***************************************************/
#include <iostream>
using namespace std;

class Transport
{
public:
	virtual ~Transport()   //虚析构函数
	{
		cout<<"in basic deconstructor"<<endl;
	}
};

class Car : public Transport
{
public:
	Car(char *name)
	{
		pn = new char[50];   //动态内存分配
		strcpy(pn,name);
		cout<<pn<<endl;
	}
	~Car()    //派生类自动定义为虚析构函数
	{
		delete pn;  //释放动态分配内存空间
		cout<<"in Car deconstructor"<<endl;
	}
private:
	char *pn;
};


void delclass(Transport *pt)   //实现释放动态分配对象的内存空间
{
	if(pt != 0)
		delete pt;
}

void main()
{
	Car *pc = new Car("king");   //动态分配内存空间
	delclass(pc);
}


 
 

程序运行结果如下:


在上述例子中,基类中定义了虚析构函数,派生类的析构函数会自动定义为虚析构函数,如果去掉基类中的virtual的话,程序执行结果如下:


从上面的结果可以看出,去掉virtual后,派生类中动态申请的内存未能得到释放,造成了内存泄露,这是需要避免的。程序员在定义基类的时候,析构函数都应该定义为虚函数,这是为了使析构更加彻底。特别是继承层次很多且派生类很多的时候,这样可以避免内存泄露。但并不是所有的类的析构函数都该被定义为虚析构函数,因为类型增加后会使程序的内存占用量增加。


发布了56 篇原创文章 · 获赞 50 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/jinpeng_cumt/article/details/52739550
今日推荐