C++基于对象的程序设计基本概念总结(六)-多态性

20 多态性

概念:指相同的对象收到不同的消息或者不同的对象收到相同的消息时产生的不同的实现动作。

C++支持两种多态:编译时多态(静态)、运行时多态(动态)。

静态多态是通过函数的重载来实现的(运算符重载实际上也属于函数的重载)。要求在程序编译的时候就知道调用函数的全部信息。静态多态性的函数调用速度快、效率高、但是缺乏灵活性,在程序运行前就决定了执行的函数与方法。

动态多态性是程序运行过程中才动态地确定操作所针对的对象,运行时多态性是通过虚函数来实现的。由虚函数实现的动态多态性就是:同一类族中不同类的对象,对同一函数调用作出不同的响应。

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

虚函数的使用方法是:

1) 在基类用virtual声明成员函数为虚函数。

2) 这样就可以在派生类中重新定义此函数,为它赋予新的功能,并能方便地被调用。在类外定义虚函数时,不必再加virtual。

3) 在派生类中重新定义此函数,要求函数名、函数类型、函数参数个数和类型全部与基类的虚函数相同,并根据派生类的需要重新定义函数体。

4) C++规定,当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数。因此在派生类重新声明该虚函数时,可以加virtual,也可以不加,但习惯上一般在每一层声明该函数时都加virtual,使程序更加清晰。如果在派生类中没有对基类的虚函数重新定义,则派生类简单地继承其直接基类的虚函数。

5) 定义一个指向基类对象的指针变量,并使它指向同一类族中需要调用该函数的对象。

6) 通过该指针变量调用此虚函数,此时调用的就是指针变量指向的对象的同名函数。

通过虚函数与指向基类对象的指针变量的配合使用,就能方便地调用同一类族中不同类的同名函数,只要先用基类指针指向即可。如果指针不断地指向同一类族中不同类的对象,就能不断地调用这些对象中的同名函数。这就如同前面说的,不断地告诉出租车司机要去的目的地,然后司机把你送到你要去的地方。

确认具体对象的过程叫关联(binding),在这里指把一个函数与类对象捆绑在一起,建立关联。

静态关联:函数重载和通过对象名调用的虚函数,在编译时即可确定其调用的虚函数属于哪一个类,其过程称为静态关联,由于是在运行前关联的,所以又叫早期关联。

动态关联:在运行时,基类指针变量指向了某个类对象,然后通过这个基类指针去调用虚函数。由于是在运行时把虚函数与对象“绑定”在一起, 因此,此过程称为动态关联。由于动态关联是在编译后运行阶段进行的,所以又称为滞后关联。

使用虚函数时的注意点:

A.只能用virtual声明类的成员函数,使他成为虚函数,而不能将类外的普通函数声明为虚函数。

B.一个成员函数在被声明为虚函数后,在同一类族中的类就不能定义一个非virtual的但是与该虚函数具有相同参数和返回值类型的函数。

怎么判断是否把一个成员函数声明为虚函数?

A.首先看成员函数所在的类是否会成为基类。然后看成员函数在类的继承后有无可能被改进功能,如果希望改变其功能的,一般把它声明为虚函数。

B.如果成员函数在类被继承后不被修改,或派生类用不到该函数,则不要把它声明为虚函数。

C.应该考虑对成员函数的调用是通过对象名还是通过基类指针或引用来访问,如果通过基类指针或引用来访问的,应该考虑用虚函数。

D.有时,在定义虚函数时,不定义其函数体,即函数体是空的。

使用虚函数,系统有一定的开销,但一个类有虚函数时,编译系统会为该类创建一个虚函数表,它是一个指针数组,存放每个虚函数的入口地址。

 

21. 当派生类的对象从内存中撤销时一般先调用派生类的析构函数,然后再调用基类的析构函数。但是,如果用new运算符建立了临时对象,若基类中有析构函数,并且定义了一个指向该基类的指针变量。在程序用带指针参数的delete运算符撤销对象时,会发生一个情况:系统会只执行基类的析构函数,而不执行派生类的析构函数。

当基类的析构函数为虚函数时,无论指针指的是同一类族中的哪一个类对象,系统会采用动态关联,调用相应的析构函数,对该对象进行清理工作。
如果将基类的析构函数声明为虚函数时,由该基类所派生的所有派生类的析构函数也都自动成为虚函数,即使派生类的析构函数与基类的析构函数名字不相同。
最好把基类的析构函数声明为虚函数。这将使所有派生类的析构函数自动成为虚函数。这样,如果程序中显式地用了delete运算符准备删除一个对象,而delete运算符的操作对象用了指向派生类对象的基类指针,则系统会调用相应类的析构函数。
虚析构函数的概念和用法很简单,但它在面向对象程序设计中却是很重要的技巧。

 

22. 纯虚函数声明: virtual 函数类型 函数名 (参数表列) = 0;

注意:
1)纯虚函数没有函数体;
2)最后面的“=0”并不表示函数返回值为0,它只起形式上的作用,告诉编译系统“这是虚函数”;
3)这是一个声明语句,最后有分号
纯虚函数只有函数的名字而不具备函数的功能,不能被调用。
纯虚函数的作用是在基类中为其派生类保留一个函数的名字,以便派生类根据需要对他进行定义。如果在基类中没有保留函数名字,则无法实现多态性。
如果在一个类中声明了纯虚函数,在其派生类中没有对其函数进行定义,则该虚函数在派生类中仍然为纯虚函数。

 

23. 象类:不用定义对象而只作为一种基本类型用作继承的类叫做抽象类(也叫接口类),凡是包含纯虚函数的类都是抽象类,抽象类的作用是作为一个类族的共同基类,为一个类族提供公共接口,抽象类不能实例化出对象。
纯虚函数在派生类中重新定义以后,派生类才能实例化出对象。

1)一个基类如果包含一个或一个以上纯虚函数,就是抽象基类。抽象基类不能也没必要定义对象。

2)在类的层次结构中,顶层或最上面几层可以是抽象基类。抽象基类体现了本类族中各类的共性,把各类中共有的成员函数集中在抽象基类中声明。

3)抽象基类是本类族的共公共接口,即就是从同一基类中派生出的多个类有同一接口。
总结:

1、派生类重写基类的虚函数实现多态,要求函数名、参数列表、返回值完全相同。(协变除外)
2、基类中定义了虚函数,在派生类中该函数始终保持虚函数的特性。
3、只有类的非静态成员函数才能定义为虚函数,静态成员函数不能定义为虚函数。
4、如果在类外定义虚函数,只能在声明函数时加virtual关键字,定义时不用加。
5、构造函数不能定义为虚函数,虽然可以将operator=定义为虚函数,但最好不要这么做,使用时容易混淆
6、不要在构造函数和析构函数中调用虚函数,在构造函数和析构函数中,对象是不完整的,可能会出现未定义的行为。
7、虚表是所有类对象实例共用的虚表剖析。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值