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
- Is it C++ behavior that I cant access derived class function through a base class function pointer or its a compiler bug?
- 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?
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.
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.
Yes, it's ok. You cannot assign to function pointer of class A
function pointer of class B
.
You can do this
fPtr = &ClassA::foo;
ClassB b;
classA* a = &b;
(a->*fPtr)();
and overriden in ClassB
function will be called.
When there is no function foo
in ClassB
, function of ClassA
will be used. Live example
First of all, I am not a C++ expert (I am trying to learn C++ so deep). So correct me if I am wrong and this an an experiment.
As part of learning about member function pointers, I was also searching for a code sample to call derived member using a base member function pointer. After going through this thread I created a code sample which is able to call derived member function even if member function is not a virtual.
I am using a Delegator to act as a Invoker. I hope it might helpful for some one. (Correct me If I am doing anything wrong)
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;
}
output:
delegate.Invoke() will call Derived::SimpleMethod() and the output will be "Derived::SimpleMethod"**