虚函数实现多态
- 多态性的本质是一个接口,多态的目的是为了接口重用,函数都能通过接口调用到适应各自对象的实现方法,也是C++面向对象编程的核心概念
- C++的多态是通过虚函数来实现的,虚函数允许子类重新定义成员函数,子类重新定义父类的做法称为覆盖/重写
- 编译器为每个类维护一个虚函数表,每个对象的首地址保存着该虚函数表的指针,同一个类的不同对象指向同一个虚函数表,基类对象会根据赋值给它的子对象的不同以不同的方式实现(调用不同的virtual函数)
- 虚函数在运行期确定函数地址是晚绑定
- 如果派生类的函数和基类的函数同名,则无论有无virtual,基类函数都会被隐藏
- 如果派生类函数和基类函数同名,且基类没有virtual,基类函数会被隐藏
- 静态成员函数不能是虚函数,内联函数不能是虚函数,构造函数不能是虚函数,析构函数可以是虚函数
虚函数实现多态
1 | #include <iostream> |
- 每个类维护一个虚函数表,类对象的vptr指向虚函数表的头部,将指向基类对象的指针指向派生类对象
- 当基类指针在调用虚函数时,会查找该对象的虚函数表,虚函数表的地址在每个对象的首地址,查找该虚函数表中的该函数进行调用
- 类比2,在普通函数中,即使将派生类对象赋给基类指针,调用的仍然是基类的成员函数
- 如果虚函数在基类与派生类中出现仅仅名字相同,而参数和返回值类型不同,即使加上virtual也不会产生多态掉过,见函数a运行结果
- 只有对象的指针或引用才能实现动态绑定,对象的点访问不能实现,如程序n.f();运行结果所示
纯虚函数
- 基类中没有定义,但是要求派生类必须定义自己的实现方法
- 而普通函数中的虚函数有定义,派生类可以定义自己的实现方法,也可以不定义
- 含有纯虚函数的类是抽象类,不能生成对象