虚函数和多态性2——抽象基类和纯虚函数
2016-10-05 16:59
253 查看
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后,派生类中动态申请的内存未能得到释放,造成了内存泄露,这是需要避免的。程序员在定义基类的时候,析构函数都应该定义为虚函数,这是为了使析构更加彻底。特别是继承层次很多且派生类很多的时候,这样可以避免内存泄露。但并不是所有的类的析构函数都该被定义为虚析构函数,因为类型增加后会使程序的内存占用量增加。
(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后,派生类中动态申请的内存未能得到释放,造成了内存泄露,这是需要避免的。程序员在定义基类的时候,析构函数都应该定义为虚函数,这是为了使析构更加彻底。特别是继承层次很多且派生类很多的时候,这样可以避免内存泄露。但并不是所有的类的析构函数都该被定义为虚析构函数,因为类型增加后会使程序的内存占用量增加。
相关文章推荐
- C++语言--多态性-8.1----多重继承、虚基类、虚函数和纯虚函数
- 【转】虚函数-虚表-虚指针-多态性-如何实现多态-纯虚函数-抽象类-转
- C++虚函数,纯虚函数,抽象基类,虚基类(转)
- C++学习之路—多态性与虚函数(二)纯虚函数与抽象类
- 【一天一篇CPP】多态性和虚函数和虚析构函数和纯虚函数和抽象类
- 虚函数与多态性,纯虚函数
- C++多态性,虚函数与纯虚函数
- 【原创】多态性、动态多态性、静态多态性、虚函数、纯虚函数、抽象类总结
- C++ 多态性 -- 虚函数、纯虚函数
- 读书笔记--C++程序设计(第2版)--12多态性与虚函数(虚析构函数,纯虚函数与抽象类)
- c++ 抽象基类、虚函数、纯虚函数 java抽象类、接口、android生命周期方法异同
- C++多态性基本概念 包括虚函数和纯虚函数
- 多态性和虚函数、纯虚函数
- 抽象基类,虚函数,纯虚函数
- 虚函数与多态性、纯虚函数
- c++基础10:继承和派生 虚函数的作用 多态性概念 纯虚函数和抽象类的概念
- 多态性,虚函数,纯虚函数,抽象类 .
- 静态联编,动态联编,类指针之间的关系,虚函数与多态性,纯虚函数,虚析构函数
- C++重载 虚函数 纯虚函数 多态性
- C++-虚函数,多态性,纯虚函数,抽象类