首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >vptr -虚拟表

vptr -虚拟表
EN

Stack Overflow用户
提问于 2009-12-02 17:05:33
回答 8查看 7.5K关注 0票数 3

有件事我还是不明白。

对于我声明的每个类,都有一个隐藏的vptr成员指向类虚拟表。

假设我有这样的声明:

代码语言:javascript
复制
class BASE
{
    virtual_table* vptr; //that's hidden of course , just stating the obvious
    virtual void foo();
}

class DERIVED : public BASE
{
   virtual_table* vptr; //that's hidden of course also
   virtual void foo();
   virtual void cho();
}

首先,我想了解一些事情,派生的和基础的vptr的成员名是否真的相同?

第二,在这种情况下会发生什么:

代码语言:javascript
复制
base* basic = new derived();

我明白了,基本变量得到的是vptr,但是这是怎么发生的呢?原因通常在发生转换时,应将派生的基本部分(包括基本的vptr)分配给基本部分,而不是派生的vptr。如果两个类中有一个同名的变量,可能会有所不同,我不知道。

第三个也是最后一个问题:当我有

代码语言:javascript
复制
 base* basic = new derived();

有没有办法调用basic -base的成员函数,即使它是虚拟的?

谢谢

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2009-12-02 17:19:08

首先,是的,它是同一个成员。它在运行基本构造函数时第一次自动分配,在运行派生构造函数时第二次分配。(在默认为空构造函数的情况下,对base的无用赋值将被优化。)

第二,没有真正的转换。事实上,派生可以被命名为“是一种”关系。在这种情况下,派生的“是”基。如果考虑派生对象的内存的第一个字节,它们与基对象的第一个字节具有相同的含义。

第三,可以按如下方式调用基本成员函数:basic->base::foo();

票数 3
EN

Stack Overflow用户

发布于 2009-12-02 17:23:27

首先,虚拟表不是C++标准的一部分。C++编译器可以自由地以任何他们认为合适的方式实现虚函数。通常他们会使用虚拟表,这是真的;但在这种情况下,他们可以以任何他们认为合适的方式实现它们。

在大多数常见的实现中,basic不会获得derivedvptr*basicvptr将指向derivedvtable,这实际上并不相同。basic只是一个指针,它所指向的对象有一个vptr。不涉及转换。在任何情况下,<代码>D9只是一个实现细节的内部名称。没有真正的类成员称为<代码>D10。

而且,只要用类名(在本例中为basic->BASE::foo())限定基类函数,就可以调用任何基类函数。

更新:为了记录起见,我尝试使用名为__vfptr (这是此编译器中vptr的内部名称)的指针在VC++2008中创建一个类,它可以正常工作,即使调试器被变量名搞糊涂了。

票数 3
EN

Stack Overflow用户

发布于 2009-12-02 17:18:36

vtable (用您的话说是virtual_table)将指向BASEDERVIVED的不同地址,前提是DERIVED覆盖了至少一个来自BASE的虚拟函数。但是,BASE的每个实例都有相同的vtable指针(DERIVED也是如此)。

当你这样做的时候:

代码语言:javascript
复制
someobject->foo();

这将转换为:

代码语言:javascript
复制
someobject->vtable[COMPILER_GENERATED_OFFET_FOR_FOO]();

vtable是一个函数指针数组,其中某个虚函数(比如foo)的偏移量对于类层次结构中的所有类都是相同的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1831635

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档