首页 > 代码库 > 虚函数 动态绑定 实现方式是:虚函数表
虚函数 动态绑定 实现方式是:虚函数表
定义为 virtual的 函数是基类期待派生类(derived class)重定义的, 基类期待 派生类继承的函数不能定义为虚函数。
动态绑定:程序能 使用继承层次中任意类型的对象,无需关心对象的具体类型。 使用这些类的程序无须区分函数在基类还是在继承类中定义的。
尽管不是必须,派生类一般会重定义基类中的虚函数。如果没有重定义,则继承基类中定义的版本。派生类中虚函数的声明原型必须与基类中的定义方式完全匹配,但有一个例外:基类中返回值是对基类性的引用(或指针)的虚函数,在派生类中虚函数可以返回 基类和派生类 的引用(或指针)。
C++默认不适用动态绑定,要触发动态绑定,得满足2条件:1,只有指定为虚函数的成员函数才能进行动态绑定,2,必须通过基类类型的引用(或指针)才能进行函数调用。
可以使用基类类型的引用(或指针)来引用基类类型或派生类类型对象。基类类型引用和指针的关键点在于:静态类型(编译时可知的引用类型或指针类型)与动态类型(运行时才可知的,指针或引用绑定的对象类型)可能不同。
即动态绑定是由实参决定的。
1 class Cshape 2 { 3 public: 4 void SetColor(intcolor){m_nColor=color;} 5 virtual void Display(void){cout<<"Cshape"<<endl;} 6 private: 7 int m_nColor; 8 }; 9 10 class Crectangle:public Cshape{ 11 public: 12 virtual void Display(void) 13 { 14 cout<<"Crectangle"<<endl; 15 } 16 }; 17 18 class Ctriangle:public Cshape{ 19 virtual void Display(void) 20 {cout<<"Ctriangle"<<endl;} 21 }; 22 23 class Cellipse:public Cshape{ 24 public: 25 virtual void Display(void) 26 {cout<<"Cellipse"<<endl;} 27 }; 28 29 voidmain() 30 { 31 Cshape obShape; 32 Cellipse obEllipse; 33 Ctriangle obTriangle; 34 Crectangle obRectangle; 35 Cshape*pShape[4]={&obShape,&obEllipse,&obTriangle,&obRectangle}; 36 for(int i=0;i<4;i++) 37 pShape[i]->Display();//动态绑定 38 }
本程序运行结果:
Cshape
Cellipse
Ctriangle
Crectangle
如果把Cshape类里面virtual void Display(void) 中的virtual去掉的话
运行结果就不一样了:
Cshape
Cshape
Cshape
Cshape
c++规定,当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数。因此,在子类从新声明该虚函数时,可以加,也可以不加,但习惯上每一层声明函数时都加virtual,使程序更加清晰。
继承层次的根类 一般要定义虚析构函数。
找工作时,面试官经常会问虚函数是如何实现的,我就懵了,以为知道以上理论虚函数就过关了,书上也没说过虚函数是如何实现的,现在在此补一补:
C++中的虚函数的实现一般是通过虚函数表(C++规范并没有规定具体用哪种方法,但大部分的编译器厂商都选择此方法)。
类的虚函数表是一块连续的内存,每个内存单元中记录一个JMP指令的地址。
注意的是,编译器会为每个有虚函数的类创建一个虚函数表,该虚函数表将被该类的所有对象共享。类的每个虚成员占据虚函数表中的一行。如果类中有N个虚函数,那么其虚函数表将有N*4字节的大小。
虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。在这个表中,主要是一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其真实反应实际的函数。这样,在有虚函数的类的实例中分配了指向这个表的指针的内存,所以,当用父类的指针来操作一个子类的时候,这张虚函数表就显得尤为重要了,它就像一个地图一样,指明了实际所应该调用的函数。
编译器应该是保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能——如果有多层继承或是多重继承的情况下)。 这意味着可以通过对象实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。
虚基类与虚函数没有关系。用于多重继承,防止二义性产生。
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。