使用基类函数指针来访问派生类的成员函数(Using base class function poin

2019-08-22 07:14发布

我使用的函数指针在我的项目,面临的问题,创建了一个测试案例,以显示它...下面的代码会失败,并在下面MSVC2005误差(用简单的话,我想通过基类的函数指针访问dervied类的函数)

错误C2440: '=':不能从 '无效(ClassB的__thiscall :: *)(无效)' 转换为 '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; 再次导致编译时错误?

Answer 1:

  1. 这是正确的行为。 认为它是这样的:的所有实例ClassB有成员ClassA::foo ,但不是所有的情况下, ClassA有成员ClassB::foo ; 只有这些实例ClassA这实际上是一个基类子对象ClassB实例有它。 因此,分配ClassB::fooClassAFoo ,然后使用ClassAFoo结合“纯” ClassA对象将尝试调用一个不存在的功能。

  2. 如果您删除fooClassB ,表达ClassB::foo实际上可以指ClassA::foo这是在继承ClassB ,所以没有问题存在。

为了详细说明1.进一步:成员指针相反的方式实际工作正常的指针。 与正常的指针,你可以指定ClassB*ClassA* (因为所有实例ClassB也都是实例ClassA ),而不是相反。 随着成员的指针,你可以指定ClassA::*ClassB::* (因为ClassB包含的所有成员ClassA ),而不是相反。



Answer 2:

好的,可以。 您不能分配的功能的指针class A的函数指针class B 。 你可以这样做

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

在被覆盖的ClassB功能将被调用。

如果没有功能fooClassB ,功能的ClassA将被使用。 活生生的例子



Answer 3:

首先,我不是一个C ++高手(我想学习C ++那么深)。 因此,纠正我,如果我错了,这一个实验。

作为学习成员函数指针的一部分,我也寻找一个代码示例使用碱成员函数指针调用派生成员。 通过这个线索去后我创建了一个代码示例,它能够调用派生成员函数,即使成员函数不是虚拟的。

我使用的是委托方充当祈求。 我希望它可能有的一很有帮助。 (纠正我,如果我做错什么)

class AbstractBase
{
protected:
    AbstractBase()
    {};

    virtual ~AbstractBase()
    {};

public:
    //Place holder method
    void SimpleMethod(void)
    {
        printf_s("\nAbstractBase::SimpleMethod");
    };
};

class Derived : public AbstractBase
{
public:
    //This overridden but not virtual.
    void SimpleMethod(void)
    {
        printf_s("Derived::SimpleMethod");
    };
};

typedef void (AbstractBase::*SimpleMethodCallback)();

class Delegator
{
private:
    AbstractBase * pbasePtr;
    SimpleMethodCallback pCallback;

public:
    Delegator()
    {
        this->pbasePtr = nullptr;
        this->pCallback = nullptr;
    };

    void RegisterCallback(AbstractBase * pbasePtr, SimpleMethodCallback callback)
    {
        if (pbasePtr == nullptr || callback == nullptr)
            throw "Delegate target or callback cannot be null";

        this->pbasePtr = pbasePtr;
        this->pCallback = callback;
    };

    void Invoke()
    {
        if (this->pbasePtr == nullptr || this->pCallback == nullptr)
            throw "Inoke cannot be performed on null target or callback";
        (pbasePtr->*pCallback)();
    }
};


int _tmain(int argc, _TCHAR* argv[])
{
    Delegator delegate;
    delegate.RegisterCallback(new Derived(), reinterpret_cast<SimpleMethodCallback>(&Derived::SimpleMethod));

    delegate.Invoke();

    return 0;
}

输出:

delegate.Invoke()将调用派生:: SimpleMethod()和输出将是 “派生:: SimpleMethod” **



文章来源: Using base class function pointer to access derived class member function