这里尽管 vp 的 dynamic type 是 Car *,我们对它使用的仍然是 Vehicle * 的函数,这是因为下面讲的 Static Binding。
15.1.3 Static Binding
C++ 中,by default,当我们使用一个 variable 的成员函数(以及成员)时,使用的是它的 static type 对应的 class 的成员和方法。这叫做 Static Binding.
(注意成员函数也只能接触它 static type 的成员,比如 Bicycle 如果有个成员叫 a 而 Vehicle 没有,一个变量的 dynamic type 是 Bicycle *,而 static type 是 Vehicle *,那么 by default,它也没法 access a 这个成员)。
class Fruit {public: int f1() {return 1;} virtual int f2() {return 2;}};class Citrus : public Fruit {public: int f1() {return 3;} int f2() override {return 4;}};class Lemon : public Citrus {public: int f1() {return 5;} int f2() override {return 6;}};int main() { Fruit fruit; Cirtrus citrus; Lemon lemon; Fruit *fptr = &lemon; Citrus *cptr = &citrus; cout << fruit.f2(); //2 cout << citrus.f1(); //3 cout << fptr -> f1(); //1, 因为 fptr static 为 Fruit*, dynamic 为 Lemon*, f1 不是一个 virtual function 因而 static binding, 使用 Fruit 的 f1(); cout << fptr -> f2(); //6, 因为 f2 是一个 virtual function 因而 dynamic binding, 使用 Lemon 的 f2(); cout << cptr -> f2(); //4, cptr static 和 dynamic 都为 Citrus* cPtr = &lemon; //更改 Citrus* 类型的变量 cPtr 的值为指向 Citrus 的子类 Lemon 的一个 object 的值, 注意这是可行的!!! cout << cptr -> f1; //3, 因为现在 cptr static 为 Citrus* 而 dynamic 为 Lemon*, f1 不是一个 virtual function 因而 static binding, 使用 Cirtrus 的 f1(); cout << cptr -> f2; //6, f2 是一个 virtual function 因而 dynamic binding, 使用 Lemon 的 f2();}
一个 polymorphic object(多态对象) 是至少有一个 virtual function 的 Class 的 一个 instance.
15.2 Abstract Classes
15.2.1 Pure virtual function 纯虚函数
一个 pure virtual function 指的是一个以 =0 为结尾 declare 的 function。这个结尾声明表示这个 function 是没有定义的,这就是“pure virtual"的意思。
这样的一个 function 在 Base class 中是不能有 implementation 的,并且要求所有的 non-abstract derived Class 提供一个 implementation.Derived classes 的 implementation 中,override 的函数就不是一个 pure virtual function 了,结尾也没有 =0.
pure virtual function 的主要目的是定义一个 interface,强制 derived classes 遵循某种 si nature (设计协议);通过这种方式,base class 定义了一个有待派生类 implemnent 的函数框架,从而实现 polymorphism。
c++
class Shape {public: virtual double area() const = 0; // pure virtual function ...};class Circle : public Shape {private: double radius;public: Circle(double r) : radius(r) {} double area() const override { // pure virtual function override return 3.14159 * radius * radius; }};
15.2.2 Abstract class 抽象类
一个 abstract class 指包含至少一个 pure virtual function 的 class.
一个 abstract class 是无法 instantiate (实例化) 的,因而也无法作为函数参数。
我们发现,其实我们是需要建立一个 abstract class 的 non-abstract derived class 的 instance,然后用一个指向 abstract base class 的 ref 或 ptr 型变量来指向它,从而实现 polymorphism。
**可以看到这就是 polymorphism 的工作方式。我们的 virtual member function 是基于抽象基类的,但是当我们写一些参数是抽象基类的指针或引用的函数时,我们可以把任何它的非抽象子类传递给这个函数,并且会使用这些子类的 member,从而只用了一个函数就涵盖了所有子类的不同情况,这就是 polymorphism. **
15.2.4 Pure Abstract Class
需要注意的是:abstract class 虽然不能 instantiate,但如果有 data member,则仍然需要一个 constructor。这是因为所有 instances of a derived class 都是从 construct base class 开始的。
c++
class Bicycle : public Vehicle {//... Bicycle(){ cout << "Bicycle default ctor\n";} Bicycle(int year_in) : year(year_in) {cout << " Bicycle int ctor\n";}};// 设我们对 base class 和其他所有 derived classes 也这样int main() { ElectricCar e1; // 输出: // Vehicle default ctor // Car default ctor // ElectricCar default ctor ElectricCar e2(1); // 输出: // Vehicle default ctor // Car default ctor // ElectricCar int ctor}
但是我们有一个新的定义:pure abstract class,指所有函数都是 abstract functions,并且没有 data members 的 class.
pure abstract class 就是一个纯 interface,不需要写 constructor;并且 compiler 会自动 implicitly 为 pure abstract class 提供一个 default constructor。(普通的 abstract class 不会这样)
15.3 容纳 different derived classes 的 ptr/ref 的 container
Polymorphism 的另一个好处就是我们可以把指向一个 base class 的不同 derived classes 的 objects 的 ptr/ref 放在同一个基类的 ptr/ref 的 container 里面。
c++
Car c(2);Bicycle b(1);ElectricCar e(5);vector<Vehicle*> fleet = {&c, &b, &e};double monthly_cost = 0;for (auto veh:fleet) monthly_cost += veh->get_insurance_amount();cout << "total insurance cost = " << monthly_cost << "\n"; //根据dynamic type 对应的 member function 产生不同结果