Reputation: 4663
Why this is not legal:
class Base
{
public:
Base(){};
virtual ~Base(){};
};
class Derived : public Base{};
void takeDerived(Derived * c){};
// main
void(*ptr)(Base*) = static_cast<void(*)(Base*)>(&takeDerived); // doesn't work
// but this work ok, as well as reinterpret_cast
// void(*ptr)(Base*) = (void(*)(Base*))(&takeDerived);
Derived
is a Base
. Why can't it be casted in function parameter? For example, I can do this easily even without casting:
void takeBase(Base* c){};
takeBase(new Derived{});
Upvotes: 0
Views: 452
Reputation: 37217
It's just designed to be that way. A Base
isn't a Derived
. The is-a relationship for class derivation can't be reversed.
The type of a function parameter means "accept", while the type of an object means "fit". Casting the type of a function changes what it accepts. It's dangerous to allow a function to accept whatever isn't what it originally accepts.
Consider this code:
class Base {};
class Derived : public Base {
public:
int t;
void useDerived() {}
};
void useDerived(Derived *d){
d->useDerived();
}
What should happen if a Base
object is passed?
Base b;
((void(*)(Base*))useDerived) (&b);
Even worse, what if another derivation of Base
is passed?
class AnotherDerived : public Base {
public:
double t;
void useDerived() {}
};
AnotherDerived ad;
((void(*)(Base*))useDerived) (&ad);
Upvotes: 1
Reputation: 510
Yes, but you're trying to do it the other way around. You cannot do
void takeDerived(Derived *c) { }
...
Base b;
takeDerived(&b);
The function pointer cast you're trying to do would enable these shenanigans; you could do
void (*ptr)(Base*) = takeDerived;
Base b;
ptr(&b); // Oops.
Then things would explode, and that would be bad.
Upvotes: 0