C++ 多态
多态 就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定
多态 意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数
C++ 使用 虚函数 实现多态
不用虚函数
例如我们可以定义一个形状 (Shape) 的类,声明一个函数 area()
来获取面积,然后分别定义两个子类 Triangle
和 Rectangle
,重新实现 area()
来获取面积
例如我们可以定义一个形状 (Shape) 的类,声明一个函数 area()
来获取面积,然后分别定义两个子类 Triangle
和 Rectangle
,重新实现 area()
来获取面积
一般情况下都会这么写
/** * file: main.cpp * author: 简单教程(www.twle.cn) * * Copyright © 2015-2065 www.twle.cn. All rights reserved. */ #include <iostream> class Shape { protected: int width, height; public: Shape( int a=0, int b=0) { width = a; height = b; } int area() { std::cout << "area in class Shape:\n"; return 0; } }; class Rectangle: public Shape{ public: Rectangle( int a=0, int b=0):Shape(a, b) { } int area () { std::cout << "area of Rectangle :\n"; return (width * height); } }; class Triangle: public Shape{ public: Triangle( int a=0, int b=0):Shape(a, b) { } int area () { std::cout << "Triangle class area :\n"; return (width * height / 2); } }; class Circle: public Shape { protected: int r; public: Circle( int a = 0 ):Shape(0,0) { r = a; } int area () { std::cout << "Circle class area :\n"; return (3.14 * r * r ); } }; // 输出 Rectangle 的面积 void echo_rectangle_area(Rectangle* rect) { std::cout << rect->area() << "\n"; } //输出 Triangle 的面积 void echo_triangle_area(Triangle* tri) { std::cout << tri->area() << "\n"; } //输出 Circle 的面积 void echo_circle_area(Circle* circle) { std::cout << circle->area() << "\n"; } // 程序的主函数 int main( ) { Rectangle rec(6,8); Triangle tri(12,13); Circle cir(5); echo_rectangle_area(&rec); echo_triangle_area(&tri); echo_circle_area(&cir); std::cout << std::endl; return 0; }
使用 g++ main.cpp && ./a.out
命令编译和运行上面代码,输出结果如下
area of Rectangle : 48 Triangle class area : 78 Circle class area : 78
我们发现 echo_xxxx_area()
函数几乎重写了三遍,只有三个还好,要是十几个 (别笑,还真有这情况),那就要写上十几遍,能否写一个函数就可以呢,比如说下面这样
// 输出形状的面积 void echo_shape_area(Shape* shape) { std::cout << shape->area() << "\n"; }
我们来试一试
/** * file: main.cpp * author: 简单教程(www.twle.cn) * * Copyright © 2015-2065 www.twle.cn. All rights reserved. */ #include <iostream> class Shape { protected: int width, height; public: Shape( int a=0, int b=0) { width = a; height = b; } int area() { std::cout << "area in class Shape:\n"; return 0; } }; class Rectangle: public Shape{ public: Rectangle( int a=0, int b=0):Shape(a, b) { } int area () { std::cout << "area of Rectangle :\n"; return (width * height); } }; class Triangle: public Shape{ public: Triangle( int a=0, int b=0):Shape(a, b) { } int area () { std::cout << "Triangle class area :\n"; return (width * height / 2); } }; class Circle: public Shape { protected: int r; public: Circle( int a = 0 ):Shape(0,0) { r = a; } int area () { std::cout << "Circle class area :\n"; return (3.14 * r * r ); } }; // 输出形状的面积 void echo_shape_area(Shape* shape) { std::cout << shape->area() << "\n"; } // 程序的主函数 int main( ) { Rectangle rec(6,8); Triangle tri(12,13); Circle cir(5); echo_shape_area(&rec); echo_shape_area(&tri); echo_shape_area(&cir); std::cout << std::endl; return 0; }
使用 g++ main.cpp && ./a.out
命令编译和运行上面代码,输出结果如下
area in class Shape: 0 area in class Shape: 0 area in class Shape: 0
哎呀,不好,发生错误了
这是为什么呢?我们传递明明是子类啊,而且子类中也有 area()
方法啊
导致错误输出的原因是,调用函数 area()
被编译器设置为基类中的版本
这就是所谓的 静态多态 ,或 静态链接 - 函数调用在程序执行前就准备好了
使用虚函数
要解决这个问题,只要把基类 Shape
中的 area()
声明为虚函数即可
/** * file: main.cpp * author: 简单教程(www.twle.cn) * * Copyright © 2015-2065 www.twle.cn. All rights reserved. */ #include <iostream> class Shape { protected: int width, height; public: Shape( int a=0, int b=0) { width = a; height = b; } virtual int area() { std::cout << "area in class Shape:\n"; return 0; } }; class Rectangle: public Shape{ public: Rectangle( int a=0, int b=0):Shape(a, b) { } int area () { std::cout << "area of Rectangle :\n"; return (width * height); } }; class Triangle: public Shape{ public: Triangle( int a=0, int b=0):Shape(a, b) { } int area () { std::cout << "Triangle class area :\n"; return (width * height / 2); } }; class Circle: public Shape { protected: int r; public: Circle( int a = 0 ):Shape(0,0) { r = a; } int area () { std::cout << "Circle class area :\n"; return (3.14 * r * r ); } }; // 输出形状的面积 void echo_shape_area(Shape* shape) { std::cout << shape->area() << "\n"; } // 程序的主函数 int main( ) { Rectangle rec(6,8); Triangle tri(12,13); Circle cir(5); echo_shape_area(&rec); echo_shape_area(&tri); echo_shape_area(&cir); std::cout << std::endl; return 0; }
使用 g++ main.cpp && ./a.out
命令编译和运行上面代码,输出结果如下
area of Rectangle : 48 Triangle class area : 78 Circle class area : 78
哇塞,终于正确了...
正如上面范例中所看到的,每个子类都有一个函数 area()
的独立实现
这就是 多态 的一般使用方式
有了多态,我们就以有多个不同的类,都带有同一个名称但具有不同实现的函数,函数的参数甚至可以是相同的