但现在,让我们对程序稍作修改,在 Shape 类中,area() 的声明前放置关键字 virtual,如下所示
多态的作用
这就是多态的一般使用方式。有了多态,您可以有多个不同的类,都带有同一个名称但具有不同实现的函数,函数的参数甚至可以是相同的。
在面向对象编程范式中,多态性往往表现为”一个接口,多个功能
class Shape {protected:int width, height;public:Shape( int a=0, int b=0){width = a;height = b;}// pure virtual functionvirtual int area() = 0;};
动态联编支持多态性
定义
编译程序在编译阶段并不能确切地指导将要调用的函数,只有在程序执行时才能确定将要调用的函数,为此要确切地指导将要调用的函数,要求联编工作在程序运行时进行,这种在 程序运行时进行的 联编工作被称为动态联编。 C++中,动态联编是在虚函数的支持下实现的 。
例子
#include<iostream>using std::cout;using std::endl;class Parent{public:virtual void show() //虚函数show{cout << "parent" << endl;}void put(){cout << "基类" << endl;}};class Son : public Parent{public:void show(){cout << "son" << endl;}void put(){cout << "派生类" << endl;}};void fun(Parent& p){p.show();}void fun(Parent& p,int) //使用占位参数重载fun。{p.put();}int main(){Parent* p = nullptr;p = new Son;Parent p1;fun(p1); //父类fun(*p); //子类cout << endl;fun(p1, 1); //父类fun(*p, 1); //子类delete p;p = nullptr;return 0;}
很明显,静态联编在编译的时候就和被调函数绑定了,只会去调用基类的put成员函数,根本不会调用派生类重写的put成员
子类对象代替父类对象作为函数入口参数
当入口参数为父类对象时,子类即便作为入口参数,最后使用的仍然是父类的方法,而入口参数是父类指针或者父类引用时,子类代替父类作为入口参数,就可以使用自己的方法。
例子
#include <iostream>using namespace std;class A{public:virtual void Show() const{cout << "A ";}};class B: public A{public:void Show() const{ cout << "B "; }};void Show(const A &obj) {obj.Show();}int main(){A a; B b;Show(a); Show(b);A *p;p = &a; p->Show();p = &b; p->Show();B *q;q = &b; q->Show();cout << endl;return 0;}
这里 line 18 传递参数为父类的引用,因此可以调用子类的函数。
