一.多态的概念
通过使用virtual关键字对多态进行支持,被virtual声明的函数被重写后具有多态特性,virtual声明的函数叫虚函数。
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Parent 7 { 8 public: 9 virtual void print() //使用virtual,变成虚函数(这个函数可能在子类被重写) 10 { 11 cout << "I'm Parent." << endl; 12 } 13 }; 14 15 class Child : public Parent 16 { 17 public: 18 void print() //由于继承关系,这里也是虚函数,只是可以省略不写 19 { 20 cout << "I'm Child." << endl; 21 } 22 }; 23 24 void how_to_print(Parent* p) 25 { 26 p->print(); // 展现多态的行为 27 } 28 29 int main() 30 { 31 Parent p; 32 Child c; 33 34 how_to_print(&p); // Expected to print: I'm Parent. 35 how_to_print(&c); // Expected to print: I'm Child. 36 37 return 0; 38 }
结果:
1 I'm Parent. 2 I'm Child.
子类中重写的函数将覆盖父类中的函数,虽然被重写覆盖了,但通过作用域分辨符(::)可以访问到父类中的函数。
二.虚函数与纯虚函数
纯虚函数和虚函数都是使用virtual关键字,只是纯虚函数在函数原型后面加上“=0”,纯虚函数没有实例化,虚函数有函数体,有实例化,定义纯虚函数是为了实现一个接口,起到一个规范的作用。
1 #include <iostream> 2 3 using namespace std; 4 5 class A{ 6 public: 7 virtual void f(const string& str)=0; 8 virtual void e() { 9 cout << "Base e() : " << endl; 10 } 11 }; 12 // 缺省实现,纯虚函数可以有函数体,但必须类的外部定义,如果子类不想实现,可以调用基类的 13 void A::f(const string& str) { 14 cout << "A f()" << str << endl; 15 } 16 17 class B : public A{ 18 public: 19 // 本质上还是重写了,只不过直接调用了基类的函数实现 20 virtual void f(const string& str){ 21 cout << "Call A::f " << endl; 22 A::f(str); 23 } 24 void e(){ 25 cout << "B e()" << endl; 26 } 27 }; 28 29 int main() 30 { 31 B b; 32 b.f("hello world"); 33 b.e(); 34 A *a = new B(); 35 // 都是多态 36 a->f("hello"); 37 a->e(); 38 return 0; 39 }
三.对象的内存布局
对象的内存布局包括两方面:成员变量的内存,指向虚函数表指针的内存,静态变量与成员函数是不占用对象内存的。