首页 > 代码库 > C++整理——虚函数的使用
C++整理——虚函数的使用
由于在公司内一直是在C语言的开发,大多也是在写业务代码,因此对C++的使用越来越生疏。然而最近在公司玩了一个编码比赛最终折戟让我重新意识到用C++的思想来设计工程的重要性。现在借blog重新梳理一下大学所学。如有疏漏不正之处,敬请指出:)
C++区别于C语言是因为它有三大特性:封装,继承,多态。
封装要求类内高内聚,类间低耦合。设计类无论在哪个工程里都是一个大学问,至今我也还在摸索TAT....
继承和多态就是今天主题,
- 什么是虚函数
虚函数是指在基类中用virtual标识符标识出来的函数。该函数与基类中其他的函数不同,如果该基类的派生类中有与合格虚函数重名的函数,那么编译器将自动重载成派生类中的重名函数,实现多态。
talk is cheap, show u the code:
1 #include <iostream> 2 3 using namespace std; 4 5 class Base 6 { 7 public: 8 void A() { cout << "Base, A()" << endl; }; 9 virtual void B() { cout << "Base, B()" << endl; }; 10 }; 11 12 class Derive : public Base 13 { 14 public: 15 void A() { cout << "Derive, A()" << endl; }; 16 void B() { cout << "Derive, B()" << endl; }; 17 }; 18 19 20 int main() 21 { 22 Base ex1; 23 Derive ex2; 24 25 // 用基类的指针指向基类,只能调用基类的方法 26 Base *ptr1 = &ex1; 27 28 // !只有用基类的指针指向派生类才是有意义的 29 Base *ptr2 = &ex2; 30 31 // 用派生类的指针只能调用派生类的方法,没有任何意义 32 Derive *ptr3 = &ex2; 33 34 // 输出基类的A, B 35 ptr1->A(); 36 ptr1->B(); 37 38 // 输出基类的A和派生类的B 39 ptr2->A(); 40 ptr2->B(); 41 42 return 0; 43 }
- 什么是纯虚函数
纯虚函数是指在基类中没有具体实现的虚函数,在C++语法中也就表现成 :
1 virtual void function() = 0;
这一类的函数由于在基类中没有实现,对于派生类而言就相当于Java中的一个接口函数,因此派生类必须要实现它。同时,有纯虚函数的基类是不能被创建实例的。对于一个工程的设计者而言,这是一个很好的设计。比如现在我有一个基类Career,我只想让派生类Teacher,Doctor等等去实现这个基类里的function而不想Career被实例化,那么我就可以在Career这个类里加入纯虚函数,将其变成一个接口类,便于工程的管理。
- 什么是虚基类
虚基类不是有虚函数的基类!
虚基类不是有虚函数的基类!
虚基类不是有虚函数的基类!
重要的事情说三遍!
由于C++支持多重继承,因此在父类的父类相同时,就很容易发生冲突,产生二义性。因此引入了虚基类的概念。
我们来看一个经典的菱形继承的问题:
1 class B : public A; 2 class C : public A; 3 class D : public B, public C;
这种场景下,由于D继承的B,C有着相同的父类,因此如果我们声明D的话,D的内存分配中将会有两份A成员的拷贝,分别是D->B->A和D->C->A。A的访问不明确,将无法编译。
因此,采用虚基类的声明方式:
1 class B : virtual public A; 2 class C : virtual public A; 3 class D : public B, public C;
在这种声明方式下,D的内存分配中将只会有一份A成员的拷贝,那么具体是通过D->B->A的路径还是D->C->A的路径访问A呢?答案是,都不通过。在这种继承方式下,必须由派生类(D)对直接基类(B,C)和间接基类(A)直接赋值。在这种情况下,只会执行最终派生类对虚基类的赋值,B和C构造函数中初始化列表里对A的赋值都不会执行。
最后,虚基类通过三个重要的函数初始化原则保证无二义性:
(1)虚基类的构造函数在非虚基类的构造函数前调用
(2)若同一层次调用了多个虚基类,那么他们的调用顺序按声明的顺序来
(3)若虚基类由非虚基类派生而来,那么先调用基类的构造函数,再调用派生类的构造函数。
牢记牢记!~
C++整理——虚函数的使用