为什么使用虚函数?什么是虚函数?虚函数是为了解决什么问题?
面向对象的三大特征:
- 封装
- 多态
- 继承
1.普通虚函数
2.虚析构函数
3.纯虚函数
4.抽象类
5.接口类
6.隐藏 vs 覆盖
7.隐藏与覆盖之间的关系
8.早绑定和晚绑定
9.虚函数表
什么是多态
相同对象收到不同消息或不同对象收到相同消息时产生的不同的动作。
静态多态 vs 动态多态
1.静态多态也叫做早绑定
//rect.h
#ifndef RECT_H
#define RECT_H
#include <iostream>
#include <stdio.h>
using namespace std;
class Rect /矩形类
{
public:
Rect();
public:
double calcArea(double width);
double calcArea(double width, double height);
};
#endif // SHAPE_H
如上面的代码,他们函数名相同,参数个数不同,一看就是互为重载的两个函数。
//mian.h
#include "Rect.h"
int main
{
Rect rect;
rect.calcArea(10);
rect.calcArea(10,20);
return 0;
}
程序在编译阶段根据参数个数确定调用哪个函数。这种情况叫做静态多态(早绑定)。
2.动态多态也叫做晚绑定
比如计算面积 当给圆形计算面积时使用圆形面积的计算公式,给矩形计算面积时使用矩形面积的计算公式。也就是说有一个计算面积的形状基类,圆形和矩形类派生自形状类,圆形与矩形的类各有自己的计算面积的方法。可见动态多态是以封装和继承为基础的。
//shape.h
#ifndef SHAPE_H
#define SHAPE_H
#include <iostream>
#include <stdio.h>
using namespace std;
class Shape//形状类
{
public:
Shape();
public:
double calcArea();
};
#endif // SHAPE_H
//shape.cpp
#include "shape.h"
Shape::Shape()
{
}
double Shape::calcArea()
{
cout << "shape" << endl;
return 0;
}
上面基类的.h文件和.cpp文件,下面我们以此基类实现矩形类和圆形类。
//rect.h
#ifndef RECT_H
#define RECT_H
#include "shape.h"
class Rect:public Shape //公有继承自形状类的矩形类
{
public:
Rect(double width,double height);
double calcArea();
private:
double m_dWidth;
double m_dHeight;
};
#endif // RECT_H
//rect.cpp
#include "rect.h"
Rect::Rect(double width, double height)
{
m_dWidth = width;
m_dHeight = height;
}
double Rect::calcArea()
{
cout << "Rect" <<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);
double calcArea();
private:
double m_dR;
};
#endif // CIRCLE_H
//circle.cpp
#include "circle.h"
Circle::Circle(double r)
{
m_dR = r;
}
double Circle::calcArea()
{
cout << "Circle" << endl;
return 3.14*m_dR*m_dR;
}
//main.h
int main()
{
Shape *shape1 = new Circle(4.0);
Shape *shape2 = new Rect(3.0,5.0);
shape1->calcArea();
shape2->calcArea();
}
如果打印结果的话,以上程序结果会打印两行"shape",因为调用到的都是父类的calcArea函数,并不是我们想要的那样去分别调用各自的计算面积的函数。
如果要想实现动态多态则必须使用虚函数。
关键字 virtual 虚函数
用virtual去修饰成员函数使其成为虚函数。
所以以上函数的修改部分如下:
在shape.h,circle.h,rect.h将calcArea方法成为虚函数,在其前面加上关键字,例如:
virtual double calcArea();
此时在去运行main函数输出的结果应该为一行Circle,一行Rect。
此时便实现预期的结果了。
多态中存在的问题
2018.9.21 未完待续。。。。