C++虚继承时产生虚基表,虚基表有神马作用?里面放了那些信息?望高手多多指教。。。

虚基类作用问题?

虚函数表对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。 在这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其容真实反应实际的函数。这样,在有虚函数的类的实例中这个表被分配在了 这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样,指明了实际所应该调用的函数。这里我们着重看一下这张虚函数表。在C++的标准规格说明书中说到,编译器必需要保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证正确取到虚函数的偏移量)。 这意味着我们通过对象实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。听我扯了那么多,我可以感觉出来你现在可能比以前更加晕头转向了。 没关系,下面就是实际的例子,相信聪明的你一看就明白了。假设我们有这样的一个类:class Base {public:virtual void f() { cout << "Base::f" << endl; }virtual void g() { cout << "Base::g" << endl; }virtual void h() { cout << "Base::h" << endl; }};按照上面的说法,我们可以通过Base的实例来得到虚函数表。 下面是实际例程:typedef void(*Fun)(void);Base b;Fun pFun = NULL;cout << "虚函数表地址:" << (int*)(&b) << endl;cout << "虚函数表 — 第一个函数地址:" << (int*)*(int*)(&b) << endl;// Invoke the first virtual functionpFun = (Fun)*((int*)*(int*)(&b));pFun();实际运行经果如下:(Windows XP+VS2003, Linux 2.6.22 + GCC 4.1.3)虚函数表地址:0012FED4虚函数表 — 第一个函数地址:0044F148Base::f通过这个示例,我们可以看到,我们可以通过强行把&b转成int *,取得虚函数表的地址,然后,再次取址就可以得到第一个虚函数的地址了,也就是Base::f(),这在上面的程序中得到了验证(把int* 强制转成了函数指针)。通过这个示例,我们就可以知道如果要调用Base::g()和Base::h(),其代码如下:(Fun)*((int*)*(int*)(&b)+0); // Base::f()(Fun)*((int*)*(int*)(&b)+1); // Base::g()(Fun)*((int*)*(int*)(&b)+2); // Base::h()这个时候你应该懂了吧。什么?还是有点晕。也是,这样的代码看着太乱了。没问题,让我画个图解释一下。如下所示:注意:在上面这个图中,我在虚函数表的最后多加了一个结点,这是虚函数表的结束结点,就像字符串的结束符“\0”一样,其标志了虚函数表的结束。这个结束标志的值在不同的编译器下是不同的。在WinXP+VS2003下,这个值是NULL。而在Ubuntu 7.10 + Linux 2.6.22 + GCC 4.1.3下,这个值是如果1,表示还有下一个虚函数表,如果值是0,表示是最后一个虚函数表。
温馨提示:内容为网友见解,仅供参考
第1个回答  2014-02-04
继承于虚基类的派生类中,虚基类的对象subobject不在固定位置(一般在内存的尾部),需要一个中介才能访问这个subobject,通常的做法是在子类对象中保留一个虚基表指针vbptr指向虚基表,通过虚基表来访问虚基类subobject。虚基表里面放什么信息要看不同的编译器厂商的实现方法,以Microsoft为例,虚基表存放的是subobject相对于vbptr的偏移量,vbptr相对于派生类对象的偏移量加上subobject相对于vbptr的偏移量就等于subobject在整个派生类的偏移量。

(c++)为什么进行了虚继承 占用的内存乘2了?
这是因为虚继承会生成一个虚基表(vbtable)指针vbptr,其中指针vbptr指向虚基表vbtable。虚基表记录了类相对于指针vbptr在对象中的偏移量。虚继承时,虚基类指针vbptr指向虚基类表vbtable,虚基类表中存放的就是数据相对于虚基类指针的偏移,从而根据偏移找到数据。在vbtable中:0:当前最近作用域的偏...

c++中虚继承、虚基类、虚函数、纯虚函数
C++动态多态性是通过虚函数实现的,虚函数允许子类(派生类)重新定义父类(基类)成员函数,子类重新定义父类虚函数的做法称为覆盖(override)或重写。在设计时,常常希望基类仅作为其派生类的一个接口。仅想对基类进行向上类型转换,使用它的接口,而不希望用户实际创建一个基类的对象。同时,创建一个纯...

麻烦大神们用用通俗的解释给我解释一下c++中的虚继承
C++允许多继承,一个类可以继承多个基类,比如:D 类继承了 B1 和 B2 两个类,这本来没什么问题。但是,如果这里的两个基类 B1 和 B2 都是从一个共同的基类 B 那里派生出来的,你就遇到了可怕的“菱形”(继承关系)。造成的问题就是,在 D 类中,B 类的内容继承了两份,不但多占用了空间,...

虚继承虚继承与虚基类的本质
性能上,虚继承带来的间接性增加了访问时间,因为每次访问都需要调整this指针。空间上,由于只存储一份虚基类,与多继承相比,虚继承节省了内存。理解虚继承和虚基类的本质对于正确使用C++的继承体系至关重要,它们在特定情况下提供了解决复杂继承问题的解决方案。

什么叫做虚基类,它有何作用
或多个副本),若只想保存这个基类的一个实例,可以将这个公共基类说明为虚基类。虚继承 是面向对象编程中的一种技术,是指一个指定的基类,在继承体系结构中,将其成员数据实例共享给也从这个基类型直接或间接派生的其它类。虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。

什么是虚基类(在c++中)?
虚基类在C++中的定义 虚基类是一种特殊的类,它在被其他类继承时,允许其它派生类之间形成共同基类的层级结构。虚基类的主要目的是解决多重继承的问题,它可以确保一个基类只在一个派生类中实例化一次,从而避免数据冗余和冲突。在C++中,通过关键字virtual来声明虚基类。当一个类被声明为虚基类时,表明...

虚继承虚拟继承入门
虚拟继承在C++编程中的作用及其使用场景并不常见,主要是因为多重继承往往不被鼓励,并且它可能会带来效率降低和空间占用问题。虽然虚拟继承在解决多重继承中的冲突问题时显得尤为重要,但在实际应用中,其价值并不明显。例如,以下代码展示了虚拟继承如何处理函数调用的歧义:当类CD继承自两个基类CB和CC,...

什么是C++虚函数,虚函数的作用和使用方
虚函数的使用方法是:1. 在基类用virtual声明成员函数为虚函数。这样就可以在派生类中重新定义此函数,为它赋予新的功能,并能方便地被调用。在类外定义虚函数时,不必再加virtual。2. 在派生类中重新定义此函数,要求函数名、函数类型、函数参数个数和类型全部与基类的虚函数相同,并根据派生类的需要...

请问高手,C++虚函数表是什么?怎么用啊?
}; 虚基类的初始化 虚基类的初始化与一般多继承的初始化在语法上是一样的,但构造函数的调用次序不同. 派生类构造函数的调用次序有三个原则: (1) 虚基类的构造函数在非虚基类之前调用; (2) 若同一层次中包含多个虚基类,这些虚基类的构造函数按它们说明的次序调用; (3) 若虚基类由非虚基类派生而...

有关虚基类和虚函数
这里C在D1,D2上继承,但有两个基类,造成混乱。因而使用虚基类,即:classB { };classD1:virtual public B { };classD2:virtualpublicB { };classC:public D1,public D2 虚函数必须是基类的非静态成员函数,其访问权限可以是protected或public,在基类的类定义中定义虚函数...

相似回答