且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-02-14 22:43:14

ol>

  • 这是正确的行为。以这种方式考虑: ClassB 的所有实例都具有成员 ClassA :: foo ,但不是所有 ClassA 有成员 ClassB :: foo ;只有那些实际是 ClassB 实例的基类子对象的 ClassA 实例才有它。因此,将 ClassB :: foo 分配到 ClassAFoo ,然后使用 ClassAFoo 结合纯 ClassA 对象将试图调用不存在的函数。


  • 如果从 ClassB 中删除​​ foo ,表达式 ClassB :: foo acutally是指在 ClassB 中继承的 ClassA :: foo ,因此没有问题。


  • 要详细说明1. further:指向成员的指针实际上与正常指针相反。使用正常指针,可以将 ClassB * 分配到 ClassA * 中(因为类B 也是 ClassA 的实例,但反之亦然。使用成员指针,可以将 ClassA :: * 分配到 ClassB :: * (因为 ClassB 包含 ClassA 的所有成员,但反之不行。


    I am using function pointer in my project, facing problem, created a test case to show it... below code fail with below error on MSVC2005 (in simple words i want to access dervied class function through base class function pointer)

    error C2440: '=' : cannot convert from '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;
    }
    

    My questions are

    1. Is it C++ behavior that I cant access derived class function through a base class function pointer or its a compiler bug?
    2. I have been playing with above case, if i comment out ClassB::foo, this code compile fine, without any further modification, Why is this so, should not fPtr = &ClassB::foo; again result in compile time error?

    1. It's correct behaviour. Think of it this way: all instances of ClassB have the member ClassA::foo, but not all instances of ClassA have the member ClassB::foo; only those instances of ClassA which are actually the base class subobject of a ClassB instance have it. Therefore, assigning ClassB::foo into ClassAFoo and then using ClassAFoo in combination with a "pure" ClassA object would try to call a nonexistent function.

    2. If you remove foo from ClassB, the expression ClassB::foo acutally refers to ClassA::foo which is inherited in ClassB, so there's no problem there.

    To elaborate on 1. further: pointers to members actually work the opposite way to normal pointers. With a normal pointer, you can assign ClassB* into ClassA* (because all instances of ClassB are also instances of ClassA), but not vice versa. With member pointers, you can assign ClassA::* into ClassB::* (because ClassB contains all the members of ClassA), but not vice versa.