虚函数
来源:互联网 发布:飞歌导航端口 编辑:程序博客网 时间:2024/05/17 23:27
1、虚函数
·虚函数表(vftable)是怎么实现的?虚函数表存放在哪里?
·虚函数表中的数据是在什么时候确定的?
·对象中的虚函数表指针(vfptr)又在什么时候赋值的?
编译器会为拥有虚函数的类创建一个虚函数表,且这个虚函数表存放在类定义模块的数据段中。模块的数据段通常存放定义在该模块的全局数据和静态数据,这样我们可以把虚函数表看作是模块的全局数据或者静态数据。
类的虚函数表会被这个类的所有对象所共享。类的对象可以有很多,但是他们的虚函数表指针都指向同一个虚函数表。因此,我们可以把虚函数表简单理解为类的静态数据成员。值得注意的是,虽然虚函数表是共享的,但是虚函数表指针并不是,类的每一个对象有一个属于它自己的虚函数表指针。虚函数表中存放的是虚函数的地址。
虚函数表的地址(即vfptr)被存放在对象的起始位置。 同时,虚函数表指针的初始化发生在构造函数的调用过程中, 但是在执行构造函数体之前,即进入到构造函数的"{"和"}"之前。 为了更好的理解这一问题, 我们可以把构造函数的调用过程细分为两个阶段,即:
1)进入到构造函数体之前。在这个阶段如果存在虚函数的话,虚函数表指针被初始化。如果存在构造函数的初始化列表的话,初始化列表也会被执行。
2)进入到构造函数体内。这一阶段是我们通常意义上说的构造函数
2、虚函数实例说明
<span style="font-family:SimSun;font-size:18px;">1)单个类中存在虚函数:class Base{public:Base(int aa, int bb): a(aa), b(bb){fun();}virtual void fun(){cout<<"Base"<<a<<endl;}int a;const int b;};类结构如下:1> class Basesize(12):1> +---1> 0| {vfptr}1> 4| a1> 8| b1> +---1> 1> Base::$vftable@:1> | &Base_meta1> | 01> 0| &Base::fun2)单继承中的虚函数:class Base{public:Base(int aa, int bb): a(aa), b(bb){fun();}virtual void fun(){cout<<"Base"<<a<<endl;}int a;const int b;};class Derived: public Base{public:Derived(int aa, int bb): Base(aa, bb){fun();}void fun(){cout<<"Derived"<<a<<endl;}virtual void nonvirtualF(){}int c;};类结构如下:1> class Basesize(12):1> +---1> 0| {vfptr}1> 4| a1> 8| b1> +---1> 1> Base::$vftable@:1> | &Base_meta1> | 01> 0| &Base::fun1> 1> class Derivedsize(16):1> +---1> | +--- (base class Base)1> 0| | {vfptr}1> 4| | a1> 8| | b1> | +---1> 12| c1> +---1> 1> Derived::$vftable@:1> | &Derived_meta1> | 01> 0| &Derived::fun //覆盖了Base::fun1> 1| &Derived::nonvirtualF3)多继承中的虚函数class Base{public:Base(int aa, int bb): a(aa), b(bb){fun();}virtual void fun(){cout<<"Base"<<a<<endl;}int a;const int b;};class Derived: public Base{public:Derived(int aa, int bb): Base(aa, bb){fun();}void fun(){cout<<"Derived"<<a<<endl;}virtual void nonvirtualF(){}int c;};class SubDrived: public Derived, public Base{public:SubDrived(int aa, int bb):Base(aa, bb), Derived(aa, bb){}virtual void SubDrivedF(){}virtual void SubDrivedFF(){}virtual void SubDrivedFFF(){}int d;};类结构如下:1> class Basesize(12):1> +---1> 0| {vfptr}1> 4| a1> 8| b1> +---1> 1> Base::$vftable@:1> | &Base_meta1> | 01> 0| &Base::fun1> 1> class Derivedsize(16):1> +---1> | +--- (base class Base)1> 0| | {vfptr}1> 4| | a1> 8| | b1> | +---1> 12| c1> +---1> 1> Derived::$vftable@:1> | &Derived_meta1> | 01> 0| &Derived::fun1> 1| &Derived::nonvirtualF1> 1> class SubDrivedsize(32):1> +---1> | +--- (base class Derived)1> | | +--- (base class Base) //Derived中包含的Base类1> 0| | | {vfptr}1> 4| | | a1> 8| | | b1> | | +---1> 12| | c1> | +---1> | +--- (base class Base)//SubDerived继承的Base类1> 16| | {vfptr}1> 20| | a1> 24| | b1> | +---1> 28| d1> +---1> 1> SubDrived::$vftable@Derived@: //SubDerived中有两个vfptr指向两个基类的vftable1> | &SubDrived_meta1> | 01> 0| &Derived::fun1> 1| &Derived::nonvirtualF1> 2| &SubDrived::SubDrivedF//该类中的虚函数地址位于声明的第一个基类的虚函数表的后面1> 3| &SubDrived::SubDrivedFF1> 4| &SubDrived::SubDrivedFFF1> 1> SubDrived::$vftable@Base@:1> | -161> 0| &Base::fun</span>
0 0
- 构造函数 虚函数
- 虚函数 inline函数
- 纯虚函数、虚函数、虚析构函数
- 虚函数,虚析构函数,虚函数表
- 普通函数,虚函数,纯虚函数
- 虚函数,纯虚函数,需析构函数
- 构造函数、析构函数、虚函数
- 构造函数 虚函数 虚析构函数
- 虚函数/构造函数/析构函数
- 构造函数&析构函数&虚函数
- 虚函数
- 虚函数
- 虚函数
- 虚函数
- 虚函数
- 虚函数
- 虚函数
- 虚函数
- hdu 5050 java大数进制转换
- .NET Design Pattern Framework 4.5 +QQ:386184911
- 论fork()函数与Linux中的多线程编程
- 泛型集合List<T> 的详细用法
- OpenGL 学习之简单的图形用户界面和交互输入
- 虚函数
- Blast使用
- 【移动开发】Ken Burns特效的幻灯片
- servlet web.xml samples
- cocos2dx中加入多盟的广告条和插屏广告
- mysql错误汇总
- C++ const用法详解
- mysql性能优化
- 激光切割机的必要配套设备直线模组