C++小知识——多态性

实现了一个接口多种实现,是面向对象的核心


一些概念

纯虚函数是虚函数再加上 = 0;
必须在子类实现这个函数,即先有名称,没有内容,在派生类实现内容

抽象类是指包括至少一个纯虚函数的类。

早期绑定:编译器在编译时,要确定每个对象调用的函数(非虚函数)的地址

通过指针或引用才是动态绑定,通过点运算是不可以的

虚函数的定义要遵循以下重要规则:
1.如果虚函数在基类与派生类中出现,仅仅是名字相同,而形式参数不同,或者是返回类型不同,那么即使加上了virtual关键字,也是不会进行滞后联编的。
2.只有类的成员函数才能说明为虚函数,因为虚函数仅适合用与有继承关系的类对象,所以普通函数不能说明为虚函数。
3.静态成员函数不能是虚函数,因为静态成员函数的特点是不受限制于某个对象。
4.内联(inline)函数不能是虚函数,因为内联函数不能在运行中动态确定位置。即使虚函数在类的内部定义定义,但是在编译的时候系统仍然将它看做是非内联的。
5.构造函数不能是虚函数,因为构造的时候,对象还是一片位定型的空间,只有构造完成后,对象才是具体类的实例。
6.析构函数可以是虚函数,而且通常声名为虚函数。

重载:指允许有多个同名函数,但是他们的参数列表不同(个数或类型)。对这两个函数的调用,在编译期间就确定了,是静态的。也就是说,他们的地址在编译期间就已经绑定了(早绑定)
重写:子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态地调用属于子类的该函数,这样的函数在编译期间是无法确定的。

封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用
多态则是为了实现另一个目的——接口重用


如何实现多态性

1、在基类的函数前加上virtual关键字,这样的函数叫虚函数
2、在派生类中重写该函数
这样,运行时将会根据对象的实际类型来调用相应的函数
如果对象类型是派生类,就调用派生类的函数;
如果对象类型是基类,就调用基类的函数。


一些例子

例1

将派生类的对象的地址赋给基类指针变量时,c++编译器进行了类型转换在这里插入图片描述
大家都知道,这个pBase实际上指向的是派生类的对象
我们希望调用派生类中的print方法,但结果却是调用了基类的print方法
原因是因为编译器在编译的时候,已经确定了对象调用的函数的地址
这个时候就需要动态绑定了,于是在运行时再去确定对象的类型以及正确调用的函数
在基类中声明成员函数时,使用virtual关键字就可以解决这个问题。请看例2.

例2

在基类中,如果一个函数被声明为虚函数,那么在所有的派生类中它都是virtual,不需要再做显式声明
在这里插入图片描述

扫描二维码关注公众号,回复: 4300355 查看本文章
例3

继承关系:CA<-CB<-C
1)指针变量ap指向基类CA的派生类CB,在调用f()时,由于基类中的f()不是虚函数,所以不具有多态性,调用基类CA中的f()
2)b是类CB的对象,直接调用其自身的方法
3)br是派生类C的引用,在调用f方法时,由于br本身是类CB(派生类C的基类),而其中的f是虚函数,具有多态性,于是调用派生类中的f方法
4)bp同3
5)指针变量ap指向基类CA的派生类CB
6)指针变量bp指向派生类C
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/CSDN_dzh/article/details/84558425