【问题标题】:Virtual table pointer and Virtual table simulation虚拟表指针和虚拟表模拟
【发布时间】:2015-10-07 02:53:45
【问题描述】:

我正在尝试模拟 vptr/vtable 概念。关于以下问题,我有 3 个问题:

1. 我没有为类 FOO 定义任何构造函数,这应该没问题,可以在 main 中看到(Foo *ptr= new FOO 可以)。 但是当我在堆上为 FooVtable::bar() 中的相同对象创建对象时,它抱怨找不到合适的默认构造函数。为什么?

2. 我看到 vptr 指向某个地址(尽管没有为 vptr 完成 new FooVTable,但我猜想 ctor 默认会这样做。这是预期的吗?),FooVtable::bar被调用但 cout 不打印该语句。为什么?

3.callsomeFun() 内部,我正在调用 foo->vptr->bar 。我在这里想要实现的是 foo->vptr->barvptr->bar 部分实际上应该调用指向成员函数的指针Foo::bar() ,我想这不是直接可能的,因此我在其中声明了void bar(Foo* foo),我想通过ptr调用Foo:bar。我是否正确地接近它,还是有更好的方法来解决这个问题?

class Foo;
struct FooVtable {
    void bar(Foo* foo)
    {
        //Foo *ptr = new Foo; //Why does this throw error as No Default constructor?
        cout<"FooVTable :  bar"; //Doesnt get printed even though gets called
    }
};
struct Foo {
    FooVtable* vptr;
    void bar(Foo *foo)
    {
        cout<<"Foo : bar";
    }
};

int callSomeFun(Foo* foo) {
    foo->vptr->bar(foo);
    return 0;
}
int main()
{
    Foo *ptr=new Foo;
    callSomeFun(ptr);
    return 0;
}

【问题讨论】:

  • 真正的 vtable 不包含实际函数,而是指向函数的指针。而这些函数会将this* 指针作为第一个参数。

标签: c++


【解决方案1】:
  1. 当我在堆上为 FooVtable::bar() 中的相同对象创建对象时,它抱怨找不到合适的默认构造函数。为什么?

对于在完全声明之前尝试使用类的情况,这是一个糟糕的错误消息。在不同的编译器上,消息可能更像是“错误:无效使用不完整类型 'class Foo'”。

解决此问题的一种方法是将完整的struct Foo 内容放在FooVtable 之上,然后使用FooVtable 的前向声明而不是Foo

  1. 我看到 vptr 指向某个地址(即使没有为 vptr 完成新的 FooVTable,我猜想 ctor 默认会这样做。这是预期的吗?), FooVtable::bar 被调用但 cout 不打印该语句.为什么?

vptr 未初始化。像指针这样的原始类型不会仅通过 new 初始化为任何类型的默认值。所以里面的东西都是垃圾。预计会有这么多。

通过带有垃圾值的指针调用函数后发生的任何事情都是未定义行为。因此,几乎任何事情都可能发生,并且没有保证的解释。

但是在这种情况下还有另一个问题:您打错了。 cout&lt;"FooVTable : bar"; 有一个 &lt;,因此会进行奇怪且无用的比较,而不是输出任何内容。

  1. foo->vptr->bar 实际上应该调用一个指向成员函数 Foo::bar() 的指针,我想这不是直接可能的

指向成员函数的指针是可能的。您可能会在迄今为止创建的情况下使用其中一种。但是,一旦您开始将继承引入场景(这正是虚函数最终有用的地方),尝试在不同类型之间解决这个问题可能会很有趣。 (我很少使用成员函数指针,以至于我不能随便说。)

我的方法正确吗,还是有更好的方法来解决这个问题?

这实际上取决于您尝试“模拟”多少实际实现以及您希望通过它实现什么。

【讨论】:

    猜你喜欢
    • 2011-03-20
    • 2014-07-07
    • 2012-02-14
    • 1970-01-01
    • 2016-07-09
    • 2022-01-03
    • 2013-10-13
    • 2020-03-02
    • 1970-01-01
    相关资源
    最近更新 更多