关于虚函数的概念讲解,可以看这篇文章:
https://blog.csdn.net/siwuxie095/article/details/71159414
以下用例子进行实际说明:
#include <iostream>
using namespace std;class Shape {
public:int width, height;Shape(int a = 0, int b = 0){width = a;height = b;}void area(){cout << "Parent class has no area" << endl;}
};class Rectangle : public Shape {
public:Rectangle(int a = 0, int b = 0) :Shape(a, b) { }void area(){cout << "Rectangle class area :" << width * height << endl;}
};class Triangle : public Shape {
public:Triangle(int a = 0, int b = 0) :Shape(a, b) { }void area(){cout << "Triangle class area :" << width * height / 2 << endl;}
};int main()
{Shape* sha1 = new Shape(10, 5);Rectangle* rec = new Rectangle(10, 5);Triangle* tri = new Triangle(10, 5);sha1->area();rec->area();tri->area();cin.get();return 0;
}
我们有形状类Shape,它有两个子类:Rectangle矩形类和Triangle三角形类。
利用多态的思想,我们希望在对不同对象下达相同指令(计算面积)的时候,不同对象可以根据自身情况完成该指令。即如果是Shape类则没有面积,而矩形和三角形各自都有计算面积的公式,以上代码看似是可以实现的,运行结果如下:
但是,这种情况实际上只是根据实例化时所属的类选择不同的area方法,属于静态多态,如果出现以下情况:
Shape* sha2 = rec;
sha2->area();
输出却为:“Parent class has no area”
明明sha2指向的地址是矩形类的地址,但是却因为实例化时用了Shape类,而导致无法正确计算面积,此时就有必要引入动态多态了。只需在Shape类中的area函数前加上virtual
关键字即可:
#include <iostream>
using namespace std;class Shape {
public:int width, height;Shape(int a = 0, int b = 0){width = a;height = b;}virtual void area(){cout << "Parent class has no area" << endl;}
};class Rectangle : public Shape {
public:Rectangle(int a = 0, int b = 0) :Shape(a, b) { }void area(){cout << "Rectangle class area :" << width * height << endl;}
};class Triangle : public Shape {
public:Triangle(int a = 0, int b = 0) :Shape(a, b) { }void area(){cout << "Triangle class area :" << width * height / 2 << endl;}
};int main()
{Shape* sha1 = new Shape(10, 5);Rectangle* rec = new Rectangle(10, 5);Triangle* tri = new Triangle(10, 5);sha1->area();rec->area();tri->area();Shape* sha2 = rec;sha2->area();cin.get();return 0;
}
输出结果如下:
而如果我们在基类中不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。只需把函数体改为= 0
即可:
#include <iostream>
using namespace std;class Shape {
public:int width, height;Shape(int a = 0, int b = 0){width = a;height = b;}virtual void area() = 0;
};class Rectangle : public Shape {
public:Rectangle(int a = 0, int b = 0) :Shape(a, b) { }void area(){cout << "Rectangle class area :" << width * height << endl;}
};class Triangle : public Shape {
public:Triangle(int a = 0, int b = 0) :Shape(a, b) { }void area(){cout << "Triangle class area :" << width * height / 2 << endl;}
};int main()
{Rectangle* rec = new Rectangle(10, 5);Triangle* tri = new Triangle(10, 5);rec->area();tri->area();Shape* sha2 = rec;sha2->area();cin.get();return 0;
}
注意此时我们无法实例化Shape类,因为它已经变成了抽象类,是作为一种规范,或者说接口而存在的。基类中定义了纯虚函数,子类必须对它进行定义,否则也是无法实例化的。
输出结果如下: