【问题标题】:Declaration for Array of pointers in Virtual DispatchVirtual Dispatch 中的指针数组声明
【发布时间】:2014-07-14 21:49:27
【问题描述】:

假设我们有如下三个函数:

int fun1()
{
    cout<<"inside fun1"<<endl;
}

int fun2()
{
    cout<<"inside fun2"<<endl;
}

int fun3(int i)
{
    cout<<"inside fun3"<<endl;
}

然后我可以声明指向函数的指针数组,用于访问前两个函数,如下所示:

int (*p[2])() = {fun1, fun2};

for (int i=0;i<2;++i)
{
    p[i]();
}

当上述函数在基类 B 中声明为虚拟时,我对声明和访问机制感到好奇。有人可以向我解释一下函数指针是如何存储在指针数组中的,以及如何使用指针。

【问题讨论】:

  • 你试过说谷歌搜索吗?喜欢this one?您是否发现此类搜索返回的信息缺乏?以什么方式?
  • @n.m. , 感谢您的答复。我无法理解如何声明指针数组的语法,因为第三个函数采用 int 参数,而前两个没有参数。
  • @CppLearner:您不能将第三个函数与 C++ 中的其他函数放在同一个数组中,它们的类型不同。这并不意味着 编译器 不能生成执行类似操作的代码。 vtable(如果这是您的编译器使用的)在语言之外。
  • 您是否对pointers to member functions 感兴趣?它们是否是虚拟的并不重要。
  • 您可以通过使用不同函数指针的结构体而不是函数指针数组来模拟这种行为。

标签: c++ arrays function-pointers virtual-functions


【解决方案1】:

首先要注意的是,指向函数的指针和指向成员函数的指针是完全不同的野兽,没有办法在它们之间进行转换。也就是说,您将无法将指向任何成员函数的指针存储到 virtualint(*)() 中,或更一般的 R(*)(Args...) 中。指向函数的指针只是存储要调用的函数的地址。

成员函数需要一个指向要传递给它们的对象的指针。如果你想存储一个指向成员函数的指针,你需要像int (B::*)()(或更一般的R(C::*)(Args...))这样声明的东西,例如:

#include <iostream>

struct B {
    virtual ~B() {}
    void         non_virtual_fn()      { std::cout << "B::non_virtual_fn\n"; }
    virtual void virtual_fn()          { std::cout << "B::virtual_fn\n"; }
};

struct D: B {
    void         non_virtual_fn()      { std::cout << "D::non_virtual_fn\n"; }
    void         virtual_fn() override { std::cout << "D::virtual_fn\n"; }
};

void (B::*members[])() = {
    &B::non_virtual_fn,
    &B::virtual_fn,
};

template <typename T, int Size>
int size(T (&)[Size]) {
    return Size;
}

int main()
{
    B b;
    D d;
    for (int i(0); i != size(members); ++i) {
        (b.*members[i])();
        (d.*members[i])();
    }
}

没有指定编译器为成员指针实际存储的内容。很可能它为非virtual 成员函数存储一个指向成员函数的指针,为virtual 函数存储一个thunk

如果您想根据存储在数组中的内容调用成员函数和非成员函数,则需要键入擦除一些详细信息,例如,使用 std::function&lt;Signature&gt;。要调用成员函数,您仍然需要为调用提供一个对象,当然,您可以使用 std::bind() 或合适的 lambda 函数来完成。

【讨论】:

  • std::bind 的大 +1。
  • 感谢 Dietmar Kühl 的详细解释。我还有一个疑问,如果有第三个函数“virtual void virtual_fn1(int value)”呢。它将如何存储在 B::*members[] 中。能否请您补充一些信息。
  • @CppLearner:由于签名不同,它无法将指向B::virtual_fn1(int)的成员函数的指针存储到void (B::*)()的数组中。为此,您需要一个 void (B::*)(int) 数组。
  • @Dietmar Kühl:好的,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多