【问题标题】:address and position of vpointer in c++c++中vpointer的地址和位置
【发布时间】:2014-11-26 16:08:21
【问题描述】:

在给定的示例中,创建了 3 个 VTable,并创建了 3 个 vptr。

但我想会有四个 VTable,其中 3 个用于基类,一个用于派生类,其中包含其派生的基类的所有虚函数地址及其自己的虚函数地址的条目。对象 obj 的大小为 12。这意味着它有 3 个 vptr。但是 vptr 是按对象创建的。这里创建了一个对象,我们怎么有3个vptr。

class Base1
{
    virtual void fun1() { cout << "Base1::fun1()" << endl; }
    virtual void func1() { cout << "Base1::func1()" << endl; }
};
class Base2 {
    virtual void fun1() { cout << "Base2::fun1()" << endl; }
    virtual void func1() { cout << "Base2::func1()" << endl; }
};
class Base3 {
    virtual void fun1() { cout << "Base3::fun1()" << endl; }
    virtual void func1() { cout << "Base3::func1()" << endl; }
};
class Derive : public Base1, public Base2, public Base3
{
public:
    virtual void Fn()
    {
        cout << "Derive::Fn" << endl;
    }
    virtual void Fnc()
    {
        cout << "Derive::Fnc" << endl;
    }
};
typedef void(*Fun)(void);
int main()
{
    Derive obj;
    std::cout << "size:" << sizeof(obj) << std::endl;
    Fun pFun = NULL;
    // calling 1st virtual function of Base1
    pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+0);
    pFun();
    // calling 2nd virtual function of Base1
    pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+1);
    pFun();
    // calling 1st virtual function of Base2
    pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+0);
    pFun();
    // calling 2nd virtual function of Base2
    pFun = (Fun)*((int*)*(int*)((int*)&obj+1)+1);
    pFun();
    // calling 1st virtual function of Base3
    pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+0);
    pFun();
    // calling 2nd virtual function of Base3
    pFun = (Fun)*((int*)*(int*)((int*)&obj+2)+1);
    pFun();
    // calling 1st virtual function of Drive
    pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+2);
    pFun();
    // calling 2nd virtual function of Drive
    pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+3);
    pFun();
    return 0;
}

在这个示例中,我希望派生类的虚拟指针位于

 (int *)*((int *)(&obj)+3)

然而,VPTR 是在

 (int *)*((int *)(&obj)+0)

有人可以解释一下吗? 提前致谢!

【问题讨论】:

  • 为什么你期待你所期待的?是什么让你有权持有任何期望? (请引用参考资料。)
  • "创建了一个对象,我们如何拥有 3 个 vptr"?该对象继承自 3 个类。

标签: c++


【解决方案1】:

派生类的表可以实现为基类表的扩展,在末尾添加任何新的虚函数。结果表可用于任一类 - 对于基类,最后的任何额外函数都将被忽略。

这意味着Derive 对象可以与三个基本子对象之一共享表,因此总共只需要三个表。

【讨论】:

    【解决方案2】:

    在多重继承中,对象中存储了多个vptr's,即每个基类一个。此外,除了独立的 vtbl 之外,还必须为基类生成特殊的 vtbl。

    更重要的一点:-

    你不应该假设 vptr 的位置是在对象的开头。它甚至可以在最后或者说在中间。这完全取决于编译器供应商如何选择实现它。

    【讨论】:

    • 就此而言,您甚至不应该假设实现使用 vtables 和 vptrs。标准没有要求。
    猜你喜欢
    • 1970-01-01
    • 2012-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-03
    • 2018-03-13
    相关资源
    最近更新 更多