使用基类函数指针访问派生类成员函数

时间:2013-04-12 12:06:52

标签: c++ visual-c++ visual-studio-2005

我在我的项目中使用函数指针,面临问题,创建了一个测试用例来显示它...下面的代码失败,MSVC2005上面出现以下错误(简单来说我想通过基类函数指针访问dervied类函数)

  

错误C2440:'=':无法转换为'void(__ thiscall ClassB :: *   )(void)'to'ClassAFoo'

class ClassA {
 public: 
    virtual void foo() 
    {
       printf("Foo Parent"); 
    }
};

typedef void (ClassA::*ClassAFoo)();

class ClassB : public ClassA {
 public:
    virtual void foo() 
    { 
        printf("Foo Derived"); 
    }
};

int main() {
    ClassAFoo fPtr;
    fPtr = &ClassB::foo;
}

我的问题是

  1. 我不能通过基类函数指针或编译器错误访问派生类函数的C ++行为吗?
  2. 我一直在玩上面的案例,如果我注释掉ClassB::foo,这段代码编译得很好,没有任何进一步修改,为什么这样,fPtr = &ClassB::foo;不应该再次导致编译时错误?

3 个答案:

答案 0 :(得分:5)

  1. 这是正确的行为。可以这样考虑:ClassB的所有实例都有成员ClassA::foo,但并非ClassA的所有实例都有成员ClassB::foo;只有那些ClassA实际上是ClassB实例的基类子对象的实例才有它。因此,将ClassB::foo分配到ClassAFoo然后将ClassAFoo与“纯”ClassA对象结合使用会尝试调用不存在的函数。

  2. 如果您从foo移除ClassB,则表达式ClassB::foo实际上是指ClassA::foo继承的ClassB,因此没有问题那里。

  3. 进一步阐述1.指向成员的指针实际上与普通指针的工作方式相反。使用普通指针,您可以将ClassB*分配到ClassA*(因为ClassB的所有实例也是ClassA的实例),但反之亦然。使用成员指针,您可以将ClassA::*分配到ClassB::*(因为ClassB包含ClassA的所有成员),但反之亦然。

答案 1 :(得分:3)

是的,没关系。您不能分配class A class B函数指针的函数指针。 你可以这样做

fPtr = &ClassA::foo;
ClassB b;
classA* a = &b;
(a->*fPtr)();

ClassB函数中的覆盖将被调用。

如果foo中没有功能ClassB,则会使用ClassA的功能。 Live example

答案 2 :(得分:0)

首先,我不是C ++专家(我正在努力学习C ++)。如果我错了,请纠正我,这是一个实验。

作为学习成员函数指针的一部分,我还在搜索使用基本成员函数指针调用派生成员的代码示例。在完成这个线程后,我创建了一个代码示例,即使成员函数不是虚函数,也可以调用派生成员函数。

我正在使用代理人充当祈求者。我希望它对某些人有帮助。 (纠正我如果我做错了什么)

stdClass Object
(
    [CustomFields] => stdClass Object
        (
            [c] => stdClass Object
                (
                    [make] => Some value
                )

        )

    [StatusWithType] => stdClass Object
        (
            [Status] => stdClass Object
                (
                    [ID] => 34
                )

        )

)

输出:

delegate.Invoke()将调用Derived :: SimpleMethod(),输出将为" Derived :: SimpleMethod" **