使用成员函数指针调用正确的虚方法

时间:2013-03-20 20:39:45

标签: c++ function virtual

在下面的示例中,我尝试将问题简化为最小值,有4个类 A,B,C,D。,它们构成了继承层次结构

程序启动时,会创建 D 类中的对象d,并调用 D 类的测试方法。此方法轮流调用 C 类的调用者方法。此方法尝试使用成员函数指针调用正确的 f 方法。在这种情况下,它应该调用与 D 类关联的 f 方法,但它会调用与 B 类关联的方法。

为什么?

class A {
    public:
    virtual void f() = 0;
};

class B : public A{
    public:
    virtual void f() { cout << "IN B" << endl;}   
};

class C : public B{
    public:
    virtual void f() { B::f(); cout << "IN C" << endl; }
    virtual void caller(){
        void (A::*cb)() = NULL;
        cb = &A::f;
        (this->*cb)();
    }
};

class D : public C{
    public:
    virtual void f() { C::f(); cout << "IN D" << endl; }
    void test(){
         caller();
    }
};

int main(){
    D d;
    d.test(); // Why does this prints only "IN B" 
    return 0;
}

UPDATE :代码实际上有效,问题与所提供的代码没有任何关系,似乎来自提供类A,B,C和提供类的库之间的版本不匹配D.

3 个答案:

答案 0 :(得分:2)

你确定它只打印“IN B”吗?我在MSVC2012上编译它,我得到了

IN B
IN C
IN D

更重要的是,你的原始代码不能在VS2012上编译,至少在我向每个类添加public之前都没有编译。 e.g:

class C : public B{
public:  // <--- here
    virtual void f() { B::f(); cout << "IN C" << endl; }
    virtual void caller(){
        void (A::*cb)() = NULL;
        cb = &A::f;
        (this->*cb)();
    }
};

答案 1 :(得分:0)

打印

IN B
IN C
IN D

所以,问题出在其他地方。

答案 2 :(得分:0)

它有效。添加public:声明。还警告过载和虚拟化的不同行为。最好的方法是使用指针或引用。

class A {
public:
    virtual void f() = 0;
};

class B : public A{
    public:
    virtual void f() { std::cout << "IN B" << std::endl;}   
};

class C : public B{
    public:
    virtual void f() { B::f(); std::cout << "IN C" << std::endl; }
    virtual void caller(){
        void (A::*cb)() = NULL;
        cb = &A::f;
        (this->*cb)();
    }
};

class D : public C{
    public:
    virtual void f() { C::f(); std::cout << "IN D" << std::endl; }
    void test(){
         caller();
    }
};

输出:

  

IN B
  IN C
  IN D