我使用的函数指针在我的项目,面临的问题,创建了一个测试案例,以显示它...下面的代码会失败,并在下面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;
}
我的问题是
- 难道C ++中,我通过一个基类的函数指针或它的编译器故障而不能访问派生类函数的行为吗?
- 我一直在玩上面的例子,如果我注释掉
ClassB::foo
,这段代码编译罚款,没有任何进一步的修改,为什么会这样,不应该fPtr = &ClassB::foo;
再次导致编译时错误?
这是正确的行为。 认为它是这样的:的所有实例ClassB
有成员ClassA::foo
,但不是所有的情况下, ClassA
有成员ClassB::foo
; 只有这些实例ClassA
这实际上是一个基类子对象ClassB
实例有它。 因此,分配ClassB::foo
成ClassAFoo
,然后使用ClassAFoo
结合“纯” ClassA
对象将尝试调用一个不存在的功能。
如果您删除foo
从ClassB
,表达ClassB::foo
实际上可以指ClassA::foo
这是在继承ClassB
,所以没有问题存在。
为了详细说明1.进一步:成员指针相反的方式实际工作正常的指针。 与正常的指针,你可以指定ClassB*
成ClassA*
(因为所有实例ClassB
也都是实例ClassA
),而不是相反。 随着成员的指针,你可以指定ClassA::*
为ClassB::*
(因为ClassB
包含的所有成员ClassA
),而不是相反。
好的,可以。 您不能分配的功能的指针class A
的函数指针class B
。 你可以这样做
fPtr = &ClassA::foo;
ClassB b;
classA* a = &b;
(a->*fPtr)();
在被覆盖的ClassB
功能将被调用。
如果没有功能foo
在ClassB
,功能的ClassA
将被使用。 活生生的例子
首先,我不是一个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” **