Closed. This question needs details or clarity。它当前不接受答案。
想改善这个问题吗?添加详细信息,并通过editing this post阐明问题。
6年前关闭。
Improve this question
我决定真正了解vtable的构建方式,因此我打开了调试器并发现了一些奇怪的东西。节点 ptr 包含一些vptr。我一直以为每个对象只有一个vptr。有人可以告诉我这是怎么回事吗? (我的意思是当基类指针指向派生类的对象时)
在
接下来,定义第二个独立类
通过
现在,您终于定义了一个
但是实际发生的是有两个__vptr字段,一个字段用于
想改善这个问题吗?添加详细信息,并通过editing this post阐明问题。
6年前关闭。
Improve this question
我决定真正了解vtable的构建方式,因此我打开了调试器并发现了一些奇怪的东西。节点 ptr 包含一些vptr。我一直以为每个对象只有一个vptr。有人可以告诉我这是怎么回事吗? (我的意思是当基类指针指向派生类的对象时)
#include <iostream>
using namespace std;
class Base
{
int base;
public:
virtual void say()
{
cout << "Hello" << endl;
}
virtual void no()
{
cout << "No" << endl;
}
};
class Base2
{
public:
virtual void lol()
{
cout << "lol" << endl;
}
};
class Derv:public Base,public Base2
{
public:
void say()
{
cout << "yep" << endl;
}
};
int main()
{
Base* ptr = new Derv();
ptr->say();
ptr = new Base();
ptr->say();
}
最佳答案
因为您有两个带有虚函数的基类,所以需要两个指针。
让我们逐步进行一下:
首先定义具有虚拟功能的Base
。因此,编译器将创建一个虚拟表,其外观大致如下(括号中给出的索引;请注意,这是一个示例,确切的表布局将取决于编译器):
[0] address of Base::say()
[1] address of Base::no()
在
Base
布局中,将存在一个指向该表的__vptr
字段(或者,如果已命名,则被命名)。当给定类型为pBase
的指针Base*
并要求调用say
时,编译器实际上将调用(p->__vptr[0])()
。接下来,定义第二个独立类
Base2
,其虚拟表将如下所示:[0] address of Base2::lol()
通过
lol
指针对Base2
的调用现在将转换为类似(pBase2->__vptr[0])()
的名称。现在,您终于定义了一个
Derv
类,该类继承自Base
和Base2
。这尤其意味着您可以同时拥有Base*
和Base2*
指向Derv
类型的对象。现在,如果您只有一个__vptr
,pBase->say()
和pBase2->lol()
将调用相同的函数,因为它们都转换为(pXXX->__vptr[0])()
。但是实际发生的是有两个__vptr字段,一个字段用于
Base
基类,而另一个字段用于_Base2
基类。 Base*
带有Base
指向__vptr
子对象,Base2*
带有自己的Base2
指向__vptr
子对象。现在Derv
虚拟表可能看起来像像这样:[0] address of Derv::say()
[1] address of Base::no()
[2] address of Base2::lol()
__vptr
子对象的Base
指向该表的开头,而__vptr
子对象的Base2
指向元素[2]
。现在调用pBase->say()
将转换为(pBase->__vptr[0])()
,并且由于__vptr
子对象的Base
指向Derv
虚拟表的开头,因此最终将按预期方式调用Derv::say()
。另一方面,如果您调用pBase2->lol()
,它将被转换为(pBase2->__vptr[0])()
,但是由于pBase2
指向Base2
子对象od Derv
,因此它将取消引用对应的__vptr
,后者指向[2]
的虚拟表的元素Derv
,其中Base2::lol
已存储。因此,现在按预期调用了Base2::lol()
。关于c++ - 虚拟表指针,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23746150/
10-11 15:38