通过指针调用base函数的qualified-id

时间:2014-12-10 09:11:11

标签: c++ pointer-to-member

如果我首先在基类foo()中定义了虚拟函数B,然后在派生类D中重写,我该如何存储B::foo的地址在指向成员函数的指针中,当调用它时,调用将表现为限定id调用(如pd->B::foo())?

示例:

struct B {
    virtual int foo() { return 1; }
};

struct D: public B {
    virtual int foo() { return 2; }
};

int main(int argc, char * argv[]) {
    D* pd = new D();
    int (B::*pf)() = &B::foo;
    int r = (pd->*pf)();
    return 0; 
}

这会调用D::foo()。我是否可以以pf调用(pd->*pf)()的方式初始化B::foo(),即使pd的动态类型是覆盖foo()的类?

(在有人问之前,我真的不想这样做,我只是好奇,如果可能的话。)

4 个答案:

答案 0 :(得分:1)

我不相信你能 我没有自己的标准,但使用vararg hack打印成员函数http://ideone.com/bRk7mG的指针值:

#include <iostream>
#include <cstdarg>
using namespace std;

struct Test
{
    void foo() {};
    virtual void bar() {}; 
    virtual void bar2() {};
    virtual void bar3() {};
};

void print_hack(int dummy, ...)
{
    va_list argp;
    va_start(argp, dummy);
    long val = va_arg(argp, long);
    cout << val << endl;
    va_end(argp);
}

int main() {
    print_hack (0, &Test::foo);
    print_hack (0, &Test::bar);
    print_hack (0, &Test::bar2);
    print_hack (0, &Test::bar3);
    return 0;
}

看起来存储在指针中的值(至少对于GCC)是对象虚拟表中的索引 对于非虚函数,它看起来像是常规函数指针。

基本上,当使用包含虚拟函数的指针到成员函数时,你被迫进行动态调度,至少据我所知。

答案 1 :(得分:1)

我同意StoryTeller,我认为不可能采用任何符合标准的方式。如果你真正想要实现的是能够使用相同的函数指针调用基类实现或派生类实现,我可以推荐的最好的是:

struct B {
    virtual int foo() { return fooB(); }
    int fooB() { return 1; }
};

struct D: public B {
    virtual int foo() { return 2; }
};

int main(int argc, char * argv[]) {
    D* pd = new D();
    int (B::*pf)() = &B::fooB;
    int r = (pd->*pf)();
    return 0; 
}

由于函数指针类型是否相同,无论函数是否为虚函数,因此在基类中创建非虚函数允许您直接获取其地址。

答案 2 :(得分:0)

为什么不这样做:

pd->B::foo() 

答案 3 :(得分:0)

我同意snakedoctor,你应该这样做:

int r = pd->B::foo()

这只是对母亲方法的呼唤。