C++中的虚函数

文章目录



多态

多态是面向对象的三大特征之一,其它两大特征分别是 封装 和 继承

在这里插入图片描述

在这里插入图片描述

所谓 多态,简单来说,就是当发出一条命令时,不同的对象

接收到同样的命令后所做出的动作是不同的

在这里插入图片描述

而书本上的定义则是:

在这里插入图片描述

其实就是在说两个概念:静态多态和动态多态

在这里插入图片描述

静态多态

静态多态,也叫 早绑定

看如下实例:

定义一个矩形类:Rect,其中有两个同名成员函数:calcArea(),显然

二者互为重载(名字相同,参数可辨)

在使用时:
在这里插入图片描述

当实例化一个 Rect 的对象后,就可以通过对象分别调用这两个函数,

计算机在编译时,就会自动调用对应的函数

在这里插入图片描述

即程序运行之前,在编译阶段就已经确定下来到底要使用哪个函数,

可见:很早就已经将函数编译进去了,称这种情况为早绑定或静态

多态

动态多态

动态多态,也叫晚绑定

看如下实例:

当前要计算面积,于是分别给圆形和矩形下达计算面积的指令,

作为圆形来说,它有自己计算面积的方法,作为矩形来说,它

也有自己计算面积的方法
在这里插入图片描述

显然,两种计算面积的方法肯定不同,即对不同对象下达相同

指令,却做着不同的操作,称之为晚绑定或动态多态

动态多态是有前提的,它必须以封装和继承为基础。在封装中,

将所有数据封装到类中,在继承中,又将封装着的各个类使其形成

继承关系

在这里插入图片描述

只有以封装和继承为基础,才能谈到动态多态,动态多态

最起码有两个类,一个子类,一个父类,只有使用三个类

时,动态多态才表现的更为明显

看如下实例:

定义一个形状类:Shape,它有一个计算面积的成员函数:calcArea()

在这里插入图片描述

再定义一个圆类:Circle,它公有继承了形状类 Shape,并有自己的

构造函数和计算面积的函数

在这里插入图片描述

圆类计算面积的成员函数在实现时:3.14 * m_dR * m_dR

在这里插入图片描述

再定义一个矩形类:Rect,它公有继承了形状类 Shape,并有自己的

构造函数和计算面积的函数

在这里插入图片描述

矩形类计算面积的成员函数在实现时:m_dWidth * m_dHeight

在这里插入图片描述

在使用时:

可以使用父类指针指向子类对象,但结果却不尽如人意,因为调用到

的都是父类的计算面积的函数,即会打印出两行calcArea

在这里插入图片描述

如果想要实现动态多态,就必须使用 虚函数

虚函数

用virtual 修饰成员函数,使其成为 虚函数

在这里插入图片描述

如下:在父类中,把想要实现多态的成员函数前加上virtual 关键字,

使其成为虚函数
在这里插入图片描述

在定义子类Circle 时,给计算面积的同名函数也加上virtual 关键字:

在这里插入图片描述

这里的virtual 关键字不是必须的,如果不加,系统会自动为你加上,

而加上了,会在后续的使用中看的更加明显,推荐在子类的定义中也

加上virtual 关键字

同理,定义子类Rect 时,给计算面积的同名函数也加上virtual 关键字:

在这里插入图片描述

最后,在使用时:

使用父类指针指向子类对象,调用函数时,调用的就是对应子类的

计算面积函数

在这里插入图片描述

程序:

Shape.h:

#ifndef SHAPE_H

#define SHAPE_H

//在每一个 .h 文件中都使用了宏定义

//宏定义是为了避免重复包含所写的

#include <iostream>

using namespace std;

  

  

class Shape

{

public:

Shape();

  

//这里加上了关键字virtual 会被继承到子类中

//子类的析构函数即便不写virtual 编译器会自动加上

//推荐给子类也写上这样看的清楚也是一种好的编程习惯

virtual ~Shape();

  

//这里加上了关键字virtual 会被继承到子类中

//子类的calcArea()即便不写virtual 编译器会自动加上

//推荐给子类也写上这样看的清楚也是一种好的编程习惯

virtualdouble calcArea();

};

  

#endif

Shape.cpp:


#include"Shape.h"

  

Shape::Shape()

{

cout << "Shape()" << endl;

}

  

Shape::~Shape()

{

cout << "~Shape()" << endl;

}

  

double Shape::calcArea()

{

cout << "Shape->calcArea()" << endl;

return0;

}

  

Rect.h:



#ifndef RECT_H

#define RECT_H

#include"Shape.h"

class Rect :public Shape

{

public:

Rect(double width, double height);

virtual ~Rect();

virtualdouble calcArea();

protected:

double m_dWidth;

double m_dHeight;

};

  

#endif

Rect.cpp:


#include"Rect.h"

  

Rect::Rect(double width, double height)

{

m_dWidth = width;

m_dHeight = height;

cout << "Rect()" << endl;

}

  

Rect::~Rect()

{

cout << "~Rect()" << endl;

}

  

double Rect::calcArea()

{

cout << "Rect->calcArea()" << endl;

return m_dWidth*m_dHeight;

}

  

Circle.h:


#ifndef CIRCLE_H

#define CIRCLE_H

#include"Shape.h"

class Circle :public Shape

{

public:

Circle(double r);

virtual ~Circle();

virtualdouble calcArea();

protected:

double m_dR;

};

  

#endif

Circle.cpp:


#include"Circle.h"

  

Circle::Circle(double r)

{

m_dR = r;

cout << "Circle()" << endl;

}

  

Circle::~Circle()

{

cout << "~Circle()" << endl;

}

  

double Circle::calcArea()

{

cout << "Circle->calcArea()" << endl;

return3.14*m_dR*m_dR;

}

  

main.cpp:


#include<stdlib.h>

#include"Rect.h"

#include"Circle.h"

  

int main(void)

{

Shape *shape1 = new Rect(3, 6);

Shape *shape2 = new Circle(5);

  

//如果calcArea()不声明为虚函数则会调用父类的calArea()函数

//输出两个 Shape->calcArea()

shape1->calcArea();

shape2->calcArea();

  

//若想通过delete父类指针来释放子类申请的内存则必须使用虚析构函数

delete shape1;

shape1 = NULL;

delete shape2;

shape2 = NULL;

system("pause");

return0;

}

  

//此即为动态多态(又称晚绑定)动态多态必须建立在封装和继承的基础上

//至少两个类不同对象收到相同消息(函数)此例即是

//

//而静态多态(又称早绑定)如在一个类中的互为重载的函数在对象调用

//两个函数即相同对象收到不同消息(函数)

运行一览:

在这里插入图片描述

转载链接:https://blog.csdn.net/siwuxie095/article/details/71159414

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值