473,382 Members | 1,720 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

Casting function parameter from Base* to Derived*

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?

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?

Jul 24 '06 #1
8 2013

Raider schreef:
reinterpret_cast<Handler*>(&DerivedHandler);
....
Is it safe?
May-be if you really know all your code, but you might use dynamic_cast
and if it would convert to null as indication you're doing something
wrong, then handle that error somehow. I have never seen this
reinterpret_cast in a C++ myself actually, but I am not a real guru I
am afraid.
http://www.cppreference.com/keywords/dynamic_cast.html

http://www.cppreference.com/keywords...pret_cast.html

Marcus Wentink

Jul 24 '06 #2

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?
No, definitely not. If it were, it would have been allowed.
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);
Well, the reinterpret_cast already tells you it's unsafe. It means as
much as
"compiler, I know this is safe". Since you have to ask, you obviously
don't know.

Now, it's rather trivial to write a wrapper functor that holds a
void(Base*) and
has an operator()(Derived*), so I suggest you use that.

HTH,
Michiel Salters

Jul 24 '06 #3
Raider schreef:
>
reinterpret_cast<Handler*>(&DerivedHandler);
...
Is it safe?

May-be if you really know all your code, but you might use
dynamic_cast
and if it would convert to null as indication you're doing something
wrong, then handle that error somehow. I have never seen this
reinterpret_cast in a C++ myself actually, but I am not a real guru I
am afraid.
dynamic_cast is unnecessary because he is certain of the class type
somehow. static_cast will return a pointer for an object with the
correct alignment for its type which reinterpret_cast won't necessarily
do.

Fraser.

Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
----------------------------------------------------------
http://www.usenet.com
Jul 24 '06 #4
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
Jul 24 '06 #5

Fraser Ross schreef:
dynamic_cast is unnecessary because he is certain of the class type
somehow.
Yes, you are right, but code can be changed, modified by people not so
certain what they are doing, and it could be an extra check? You need
some extra check here somewhere, for the fact when another coder
changes your code to something where things can go wrong.

I have never seen reinterpret_cast used actually. Why and where would
you use reinterpert_cast? I've been programming C++ for some years now,
and the casts frequently used are the static and dynamic.
static_cast will return a pointer for an object with the
correct alignment for its type which reinterpret_cast won't necessarily
do.
Correct alignment?

Jul 25 '06 #6
ma*********@hotmail.com wrote:
Fraser Ross schreef:
>dynamic_cast is unnecessary because he is certain of the class type
somehow.

Yes, you are right, but code can be changed, modified by people not so
certain what they are doing, and it could be an extra check? You need
some extra check here somewhere, for the fact when another coder
changes your code to something where things can go wrong.

I have never seen reinterpret_cast used actually. Why and where would
you use reinterpert_cast? I've been programming C++ for some years now,
and the casts frequently used are the static and dynamic.
>static_cast will return a pointer for an object with the
correct alignment for its type which reinterpret_cast won't necessarily
do.

Correct alignment?
If you read the OP's message carefully, you'll see that the OP is not talking
about conversions between 'Base*' and 'Derived*' types, but rather about
conversions between 'void (*)(Base*)' and 'void (*)(Derived*)' types. Neither
'static_cast' nor 'dynamic_cast' is applicable here. Only 'reinterpret_cast' can
be used, but its safe usage is so limited as to make it completely useless in
this case.

--
Best regards,
Andrey Tarasevich
Jul 25 '06 #7

Andrey Tarasevich schreef:

conversions between 'void (*)(Base*)' and 'void (*)(Derived*)' types. Neither
'static_cast' nor 'dynamic_cast' is applicable here. Only 'reinterpret_cast' can
be used
Ah, yes, I understand, thanks!

Jul 25 '06 #8
Andrey Tarasevich wrote:
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?
I have a layered application archirecture. Some layer is generating
event and pass it to the next and so on. I want to separate layers form
each other giving simply one door between them:

void HandleEvent(Event&);

Stright way is to create personal door for each event
class IEventHandler
{
void HandleEvent(Event1&);
void HandleEvent(Event2&);
void HandleEvent(Event3&);
....
}

But:
1. such interface will grow when adding new event types
2. each HandleEvent() will contain the same code to dispatch events by
another (not event type) characteristics - in real code I have std::map
not with typeid(Event) key, but with a tuple of event characterictics
(with typeid(Event) as not even first member).

Currently I have simple handlers registration like this:
void SomeHandler(SomeEvent&)
{
// handle event of type SomeEvent
// form MODULE_A initiated by SUBSYSTEM_X
}

int main()
{
Handlers.Register<SomeEvent>(MODULE_A, SUBSYSTEM_X, SomeHandler);
...
}

Jul 25 '06 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: James Brown | last post by:
I have two classes, a base class, and a class base { public: base(); virtual void foo() = 0; }; class derived : public base
3
by: Kurt | last post by:
i just can't figure out why something im doing is not working correctly.... public interface IInterface { int someProperty { get; set; }
0
by: Kurt Lange | last post by:
no... the array is created dynamically. and no... that defeats the purpose of what im trying todo.. encapsulate all initializing of variables in base class... derive from it... by deriving...
2
by: Edward Diener | last post by:
In C++ an overridden virtual function in a derived class must have the exact same signature of the function which is overridden in the base class, except for the return type which may return a...
23
by: René Nordby | last post by:
Hi there, Is there anyone that knows how to do the following? I have a class A and a class B, that 100% inherits from class A (this means that I don't have other code in class B, than...
6
by: Spoon | last post by:
Hello everyone, I'm writing code where I can receive two kinds of packets. The first 12 octets are common to both packet types, i.e. they have the same semantics. The 1st type has 4 more...
9
by: Jess | last post by:
Hello, It seems both static_cast and dynamic_cast can cast a base class pointer/reference to a derived class pointer/reference. If so, is there any difference between them? In addition, if I...
9
by: Naomi | last post by:
I need to make software engineering decision to do with using a derived data type in a container class. So for example, if I have an Edge class, and I want to make a Edge object which contains two...
9
by: Taras_96 | last post by:
Hi everyone, I was experimenting with static_cast and reinterpret cast #include <iostream> struct A1 { int a; }; struct A2 { double d; }; struct B : public A1, A2
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.