当前位置:首页 > 天道酬勤 > 正文内容

虚函数指针(纯虚函数和虚函数实例)

张世龙2021年12月21日 09:44天道酬勤1310

多态性分为运行时的多态性(虚函数改写)、编译时的多态性)过载、构造函数多态性。

1 )编译时多态性)相同的对象即使收到相同的消息,也会发生不同的函数调用。 一般通过函数重载来实现,在编译时实现绑定,是静态绑定。

2 )运行时多态性)不同的对象在收到相同的消息时发生不同的动作,一般是通过虚函数实现的。 运行时的多态性通过virtual函数的改写和动态绑定来实现。

virtual是指告诉编译器函数使用动态绑定而不是静态绑定。

实现多态性主要采用引用和指针。 值传递是由类型编译器通过复制数据来决定的。 多态性是指类型在等待执行期间后决定的,因此不使用按值传递的方式传递多态性参数。

1 多态的作用

包可以使代码模块化。

对于继承,可以扩展现有代码。

多态性是为了接口的再利用。 不要为同一功能添加复杂的名称。

2 多态最常见的用法

多态性最常见的用法是声明基类的指针。 通过使用此指针指向任意子类的对象,然后调用相应的虚函数,可以实现不同的方法,具体取决于所指向的子类。 如果不使用虚函数,即不使用c多态性,则在利用基类指针调用对应的函数时,总是受限于基类函数本身,无法调用子类改写的函数。 由于没有多态性,函数调用的地址是恒定的,固定的地址总是被同一函数调用。 这样就无法实现一个接口、多个方法的目的。

3 扩展了解隐藏规则

本来不仅仅是区分超载和覆盖是困难的,但是由于c的隐藏规则,问题的复杂性急剧增加。

这里的“隐藏”意味着派生类函数屏蔽了与其同名的基类函数。 规则如下。

1 )派生类函数与基类函数同名,但参数不同时。 此时,无论是否存在virtual关键字,基类的函数都会隐藏。 (请注意不要与重载混淆)

2 )如果派生类函数与基类函数相同,且基类没有virtual关键字,则基类函数将被隐藏。 (请注意不要和盖子混淆。

4 多态实现过程

动态多态性发生在程序执行期,是一种动态绑定。 动态多态性通过继承、虚函数、指针实现。 程序决定运行时调用的函数,通过从父指针调用子类的函数,可以使父指针具有各种各样的形态。

4.1具有基类的成员函数被声明为虚函数后,可以在后续的派生类中重新定义它。 但是,在定义时,函数的原型、函数名称、参数个数和参数类型的顺序必须与基类的原型完全相同。

4.2要通过虚函数实现运行时的多样性,必须通过基类指针指向派生类对象。

4.3虚函数具有继承性,如果基类中明确声明了虚函数,则派生类中函数名前面的virtual可以省略。 因为系统根据基类虚函数的原型是否完全相同来判断虚函数是否是虚函数。 一个虚函数无论公有继承多少次,它仍然是虚函数。

4.4要使用虚函数,派生类必须是基类的公共派生。

4.5虚函数必须是所属类的成员函数,既不是友元函数也不是静态成员函数。 因为虚函数调用决定在特定对象类中激活哪个函数。

4.6构造函数不能是虚函数,但构造函数可以是虚函数。

5 多态中的虚函数

虚函数只是定义同样的动作,通过重新加载到特定个体的函数中来实现个体不同的动作方式。

虽然名称相同,表示共同的行为,但重新加载的派生类有差异。 但是,虚函数的指针有不同的指向()不同的派生类对象),因此可以产生不同的行为。

虚函数的主要作用是将该类和各派生类的公共功能抽象出来实现公共部分,然后在派生类中写入特定的代码。 因此,从多个对象中抽象出功能交叉非常重要,交叉中的功能是利用虚函数来实现的。 基类有时会为这些虚函数提供默认的实现函数。

6 纯虚函数与抽象类

为了便于使用多态性特性,程序员经常需要在基类中定义虚拟函数。 基类本身通常生成对象是没有道理的。 例如,动物可以作为基类派生出猴子、犀牛等子类,但动物自身生成对象显然是不常识的。

为了解决上述问题,如果引入纯虚函数的概念,并将函数定义为纯虚函数,则编译器需要重装才能在派生类中实现多态性。 包含纯虚拟函数的类称为抽象类,不能生成对象。 这样就很好地解决了上述两个问题。

纯函数是指不指定实现的函数。 如果类只包含纯虚函数,或者从纯虚函数继承而未提供实现,则该类为抽象类。 不能在程序中创建抽象类对象。 只能使用抽象类进行派生。 所有从抽象类派生的类都必须实现纯虚函数。 线性函数用纯指示符=0声明,代码如下:

虚拟区域()=0;

抽象类提供通用的功能,但太通用了,无法实现具体的功能。

引入抽象基类和纯虚函数的主要目的是实现接口的效果。 在面向对象编程语言中,为了更好地表示客观世界。 所以有些类什么也不实现就只能提供一个共享的接口。 这就是纯虚函数,包含纯虚函数的基类就是抽象基类。

7 多态性是如何实现程序的可扩展性?

派生类是一个特殊的基类,如本科生、硕士生、博士生都是由学生级派生的。 因为所有的学生都要写论文,所以基类(学生班)有“写论文”的虚函数。 但是,不同种类的学生写论文的要求不同,所以本科生、硕士生、博士生的班级中有与虚函数对应的“书论”

文”函数。当需要向所有学生布置写论文的任务时,可以用一个学生类的指针遍历所有的学生。由于多态性,每类学生执行的是自己类新增的“写论文”函数,按照自己类规定的要求写论文。如果学校决定要招收工程硕士,那么系统中必须有一个“工程硕士”的类。工程硕士也是一类学生,所以也从学生类派生。工程硕士也要写论文,论文要求和其他几类学生不同,所以工程硕士类也要有一个“写论文”的函数。如果建好了工程硕士这个类,向全校学生布置写论文的工作流程还和以前一样。由此可见,当扩展系统时,只需要增加一些新的类,而主程序不变。

多态的关键在于编译器行为:建立虚函数表、为对象建立虚函数指针。

8 动态多态实例

#include <iostream> #include <string> using namespace std; class Graph { protected: double x; double y; public: Graph(double x, double y); virtual void showArea(); }; Graph::Graph(double x,double y) { this->x=x; this->y=y; } void Graph::showArea() { cout<<"couting Graph's Area"<<endl; } class Rectangle:public Graph { public: Rectangle(double x, double y):Graph(x,y){}; void showArea(); }; void Rectangle::showArea() { cout<<"Rectangle's area: "<<x*y<<endl; } class Triangle:public Graph{ public: Triangle(double d, double h):Graph(d,h){}; void showArea(); }; void Triangle::showArea() { cout<<"Triangle's area: "<<x*y*0.5<<endl; } class Circle:public Graph { public: Circle(double r):Graph(r,r){}; void showArea(); }; void Circle::showArea() { cout<<"Circle's Area: "<<3.14*x*y<<endl; } int main() { Graph * g; Rectangle rec(8,5); g = &rec; g->showArea(); Triangle tri(6,5); g = &tri; g->showArea(); Circle cir(2); g = &cir; g->showArea(); system("pause"); return 0; } /* Rectangle's area: 40 Triangle's area: 15 Circle's Area: 12.56 */

-end-

扫描二维码推送至手机访问。

版权声明:本文由花开半夏のブログ发布,如需转载请注明出处。

本文链接:https://www.zhangshilong.cn/work/26232.html

分享给朋友:

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。