Re: Casting function parameter from Base* to Derived*
Raider wrote:
I have simple class hierarchy (without multiple inheritance):
class Base {};
class Derived : public Base {};
class DeepDerived : public Derived {};
// ... a lot of types
Is it ok to cast void(Base*) to void(Derived*) if I know exactly what I
will pass Derived* as a parameter?
What you actually cast in your code below is 'void (*)(Derived*)' to 'void
(*)(Base*)', not the other way around. This is not a standard conversion (in
either direction, BTW), which means that in can't be done implicitly. This cast
can be explicitly forced with 'reinterpret_cast'. However, you can't use the
resultant pointer value in order to call the function. The only thing you can do
with the resultant value is to cast it back to 'void (*)(Derived*)' at a later
time, i.e perform a "round trip" conversion 'void (*)(Derived*)' -> 'void
(*)(Base*)' -> 'void (*)(Derived*)'. The final value can be used in a call, but
the intermediate 'void (*)(Base*)' value cannot be.
I want to register different handlers for different types using
std::map:
typedef void Handler(Base*);
std::map<const std::type_info*, Handler*> Handlers;
Imagine code like this:
void DerivedHandler(Derived*);
Handlers[&typeid(Derived)] =
reinterpret_cast<Handler*>(&DerivedHandler);
Base* P = ...;
std::map<const std::type_info*, Handler*>const_iterator It =
Handlers.find(&typeid(*P));
if (It != Handlers.end()) (*(It->second))(P);
Is it safe?
No. In order to "fix" the code you'd have to complete the "round trip"
conversion by adding an extra cast:
std::map<const std::type_info*, Handler*>const_iterator It =
Handlers.find(&typeid(*P));
if (It != Handlers.end())
reinterpret_cast<void (*)(Derived*)>(t->second)(P);
But the need for a hardcoded cast essentially defeats the purpose of the code,
as I understand it. What you are trying to use is not a viable approach to
run-time type-based dispatch, as long as you care about the safety of the code.
Without knowing more details about what you are trying to implement it is hard
to understand why you even need such a dispatcher and, therefore, hard to
suggest an alternative technique. Can you provide more details?
--
Best regards,
Andrey Tarasevich