C++ 学习之旅(16)——虚函数与纯虚函数virtual

    科技2022-07-14  133

    关于虚函数的概念讲解,可以看这篇文章:

    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类,因为它已经变成了抽象类,是作为一种规范,或者说接口而存在的。基类中定义了纯虚函数,子类必须对它进行定义,否则也是无法实例化的。

    输出结果如下:

    Processed: 0.010, SQL: 8