【问题标题】:Getting a pointer to a (pure) virtual function from a base class instance从基类实例获取指向(纯)虚函数的指针
【发布时间】:2019-03-12 16:03:53
【问题描述】:

我有以下 c++11 代码,它可以工作,但我预计它会崩溃甚至无法编译。检索指向纯虚成员函数的指针应返回空指针或无效指针,或者应被编译器阻止。我想了解它为什么有效。

我知道还有其他(更好的)编码方式,这是一个纯粹的理论问题,用于理解语法的作用。

#include <iostream>
#include <functional>

class Abstract
{
public:
    void foo()
    {
        auto func = std::bind(&Abstract::virtualFoo, this);
        func();
    }

protected:
    virtual void virtualFoo() = 0;
};


class Derived1 : public Abstract
{
private:
    void virtualFoo() override
    {
        std::cout << "I am Derived1\n";
    }
};

class Derived2 : public Abstract
{
private:
    void virtualFoo() override
    {
        std::cout << "I am Derived2\n";
    }
};


int main(int argc, char *argv[])
{
    Abstract * a1 = new Derived1;
    Abstract * a2 = new Derived2;

    a1->foo();
    a2->foo();

    return 0;
}

意图很明确,在基类函数 foo() 中我要获取派生虚函数的指针。

但是,据我了解,它不应该工作,甚至不应该使用纯虚函数编译。对于非纯虚函数,它应该执行基类函数。但是,看到它编译并产生预期的输出,我感到非常惊讶:它打印“I am Derived1”然后“I am Derived2”

&amp;Abstract::virtualFoo 如何在不知道指向实际对象的指针的情况下返回有效指针,这是访问 vtable 所必需的???

在线 C++ 链接:https://onlinegdb.com/SJfku8rvV

对我来说,有效的语法应该是:

        auto func = std::bind(&this->virtualFoo, this);

由于取消引用this 应该实际访问vtable 并返回一个函数指针。但是c++11不这么想。

【问题讨论】:

  • virtualFoo 在 vtable 中有一个条目,但它在 ABC 中的值为零。
  • 如果不是使用函数指针然后调用 func(); 你只需调用 virtualFoo(); 你会得到相同的输出,我真的不明白你为什么认为这不应该工作
  • 虽然std::bind 在某些情况下可能很有用,但大多数用例应该改用 lambda。在您的代码中包含此处显示的这种情况。
  • @Botje :是的,但是在这种情况下,为什么不将空指针传递给绑定?
  • @Someprogrammerdude :这纯粹是一个 MCVE,我这样做是为了避免直接调用 virtualFoo() 来通过显式检索指针来说明问题。我当然知道 lambdas。

标签: c++ function pointers virtual derived


【解决方案1】:

&amp;Abstract::virtualFoo 如何在不知道指向实际对象的指针的情况下返回有效指针,这是访问 vtable 所必需的???

您已将函数声明为虚拟函数。编译器知道该函数是虚拟的。标准要求通过成员函数指针调用进行虚拟调度。

编译器将必要的信息存储到成员函数指针中以实现这一点。请注意,成员函数指针不一定只是指向单个地址的指针。它可以包含更多。

编译器实现这一点的确切方式是实现定义的。

【讨论】:

  • 谢谢。例如,这意味着不可能将它们转换为带有“this”作为第一个参数添加的普通函数指针,并且它们也不能转换为 uintptr_t。换句话说,这些不是指针类型,而是更复杂的结构。
  • @galinette 是的,[basic.compound] 将“指向 cv void 或对象或函数的指针与“指向非静态类成员的指针”区分开来另见[dcl.ptr][dcl.mptr]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多