C++语言的多态性与虚函数
小标 2018-07-10 来源 : 阅读 1209 评论 0

摘要:本文主要向大家介绍了C++语言的多态性与虚函数,通过具体的内容向大家展示,希望对大家学习C++语言有所帮助。

本文主要向大家介绍了C++语言的多态性与虚函数,通过具体的内容向大家展示,希望对大家学习C++语言有所帮助。

一、什么是多态

C++有三大特性,封装、继承、多态。多态是面向对象程序设计的一个重要特征。利用多态性可以设计和实现一个易于扩展的系统。多态就是一个事物有多重状态,在C++程序设计中,多态性是指具有不同功能的函数可以用一个函数名,这样就可以用同一个函数名实现不同的功能。

从系统的角度看,多态分为静态多态和动态多态。静态多态是利用重载实现的,在程序编译时确定要调用的是哪个函数,因此静态多态又称为编译时多态。动态多态是利用虚函数实现的,在程序执行期间才动态的确定操作所针对的对象,因此动态多态又称为运行时多态。

动态多态和虚函数主要研究的是:当一个基类被继承为不同的派生类时,各派生类可以使用与基类成员相同的成员名,如果在运行时用同一个成员名调用类对象的成员,那么会调用哪一个对象的成员?也就是,通过继承而产生了相关的不同派生类,与基类成员同名的成员在不同的派生类中有不同的含义。即“一个接口,多个方法”。

 

二、虚函数

1、虚函数的作用

我们知道在同一个类中是不能定义两个名字相同、参数个数和类型完全相同的函数,否则就是重复定义。但是在类的继承层次结构中,在不同的层次中可以出现名字相同、参数个数和类型相同而功能不同的函数(这是因为类域的原因,即他们在不同的作用域内)。这时系统会根据同名覆盖的原则决定调用的对象。

例:

   

class Student
{
public:
      void display()
      {
          cout << _age << endl;
      }
protected:
      int _age;
};
 
class Student1 :public Student
{
public:
     void display()
     {
         cout << _name << "--" << _age << endl;
     }
protected:
      char _name;
};


 

 

如果在main函数中有如下定义:

Student1 s1;

s1.display();

则这时调用的就是Student1中的display函数。如果要通过s1调用student中的display函数的话,则必须加上基类名限制作用域,如:s1.Student::display();

 

Student p;

p=s1;

p.display();

这时p调用的是基类的display函数。

那么有没有一种方法,用同一种调用形式,既能调用派生类又能调用基类的同名函数?即不通过不同的对象名去调用不同派生层次中的同名函数,而是通过指针调用它们。

例如:用p->display();可以调用不同派生层次中的display函数,只需要在调用之前给指针变量p赋不同的值,使之指向不同的类对象即可。

C++中的虚函数就是用来解决这个问题的。虚函数的作用是允许在派生类中重新定义与基类同名的函数,并可以通过基类指针或引用来访问基类和派生类中同名函数。

 

2、如何声明虚函数

对上面的程序做一点修改,在Student类中声明display函数时,在最左端加一个关键字virtual,即:virtual void display(); 这样就将Student中的display函数声明为虚函数。

如果在main函数中有如下语句:

Student s; //基类的对象

Student1 s1; //派生类的对象

Student *p; //指向基类的指针

p=&s; //让p指向基类对象

p->display(); //调用的是基类的display函数

p=&s1; //让p指向派生类对象

p->display(); //调用的是派生类的display函数

现在用一个指针变量p(指向基类对象的指针变量),就可以调用同一类族中的不同类的虚函数。本类,基类的指针是用来指向基类对象的,如果用它来指向派生类的对象,则进行指针类型的转化,即基类指针指向的是派生类中从基类中继承的部分。在程序修改之前,是无法通过指向基类的指针调用派生类中的函数的。但是声明为虚函数之后,在派生类中的虚函数取代了基类原来的虚函数,因此在使用基类指针指向派生类对象后,调用虚函数就是调用了派生类的虚函数。

当把基类的某个成员函数声明为虚函数之后,允许在派生类中对该函数重新定义,赋予它新的功能,并可以通过指向基类的指针指向同一类族中不同类的对象,对同一函数调用做出不同的响应。

 

三、虚函数的使用方法

1、在基类中用virtual声明成员函数是虚函数。(在类外定义时不需要再加virtual)

 

2、在派生类中重新定义虚函数,要求函数名,函数类型,参数个数和类型完全与基类中的虚函数相同,根据自己的需求定义函数体。C++中规定,当一个成员函数被声明为虚函数后,在派生类中的同名函数都是虚函数。如果在派生类中没有对虚函数重新定义,则派生类简单的继承基类的虚函数。

 

3、定义一个指向基类对象的指针变量,并使他指向同一类族中需要调用该函数的对象。通过该指针变量调用此虚函数,就相当于指针变量所指向的对象的同名函数。

 

4、函数重载处理的是同一层次上的同名函数问题,因此是横向重载。虚函数处理的是类的派生层次上的同名函数问题,属于纵向重载。与重载不同的是,虚函数要求函数的首部完全相同。

 

5、函数重载和通过对象名调用的虚函数,在编译期间即可确定调用的虚函数属于哪一个类,其过程称为静态关联。在运行阶段,基类变量先指向某一个类对象,然后通过此指针变量调用该对象中的函数,这种过程称为动态关联。

 

四、什么时候使用虚函数

1、因为虚函数是用于类的继承层次结构中的,所以只能将类的成员函数声明为虚函数,而不能将普通函数声明为虚函数。

2、一个成员函数被声明为虚函数后,就不能再同一类族中再定义一个非virtual的但是与虚函数首部相同的函数了。

3、如果一个类作为基类,它的成员函数可能会在派生类中发生改变,则应声明为虚函数。

4、如果是通过指向基类对象的指针调用派生类中成员函数,则应声明为虚函数。

 

5、使用虚函数,系统会有一定的空间开销。当一个类中有虚函数时,编译系统会为该类构造一个虚函数表,它是一个指针数组,用来存放每个虚函数的入口地址。但是系统在进行动态关联时的时间开销很少,所以多态很高效。

 

6、一般将析构函数声明为虚析构函数,即时基类不需要析构函数,也要显示的定义一个函数体为空放入虚析构函数,以保证在撤销对象动态分配空间时能得到正确的处理。

 

五、纯虚函数和抽象类

1、什么是纯虚函数

有时在类中将某一成员声明为虚函数,并不是因为基类本身的要求,而是因为派生类的需求,在基类中预留一个函数名,具体功能留给派生类区定义。这种情况下就可以将这个纯虚函数声明为纯虚函数。其一般形式是:

virtual 函数类型 函数名 (参数列表) =0;

注意:

纯虚函数没有函数体。最后的“=0”只是一种形式,告诉编译系统,它是一个纯虚函数,留在派生类中定义,并没有实际意义。纯虚函数只有在派生类中定义了之后才能被调用。如果在一个类中声明了纯虚函数,而在派生类中没有对该函数定义,则该虚函数在派生类中仍然为纯虚函数。

 

2、抽象类

含有纯虚函数的类就成为抽象类。抽象类只是一种基本的数据类型,用户需要在这个基础上根据自己的需要定义处各种功能的派生类。抽象类的作用就是为一个类族提供一个公共接口。抽象类不能定义对象,但是可以定义指向抽象类的指针变量,通过这个指针变量可以实现多态。

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!


本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程