By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,202 Members | 1,635 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,202 IT Pros & Developers. It's quick & easy.

Question on c++ faq 21.2 Derived** -> Base**

P: n/a
Dear all,
assuming that through a mechanism, for example reflexion, the Derived**
is known explicitly. Would it be legal (and "moral") to do this
conversion by a cast (probably reinterpret would work here)? The
conversion is done for this purpose: I have an
std::map<std::string, Base*>. I want to "associate" Derived* handles to
the stored Base* so when Base* in the map changes (ie points another
address), the Derived* handle outside of the map is updated
automatically to point to the new address also. Actually what I do for
the moment is that I make the association using eg
Map.Associate(std::string name, Derived*&), where Map is a class
containing the mentioned std::map but I guess this is related to the
title of the post (Is Derived*& -Base*& moral?). This is the only
reason for the conversion, the Derived objects are to be handled only by
the Derived* pointers. Could there be a better solution that I fail to
see? I need to use a polymorphic container because I have several
Derived* types. Thanks,

filimon
Mar 3 '07 #1
Share this Question
Share on Google+
3 Replies


P: n/a
Filimon Roukoutakis wrote:
Dear all,
assuming that through a mechanism, for example reflexion, the Derived**
is known explicitly. Would it be legal (and "moral") to do this
conversion by a cast (probably reinterpret would work here)? The
conversion is done for this purpose: I have an
std::map<std::string, Base*>. I want to "associate" Derived* handles to
the stored Base* so when Base* in the map changes (ie points another
address), the Derived* handle outside of the map is updated
automatically to point to the new address also. Actually what I do for
the moment is that I make the association using eg
Map.Associate(std::string name, Derived*&), where Map is a class
containing the mentioned std::map but I guess this is related to the
title of the post (Is Derived*& -Base*& moral?). This is the only
reason for the conversion, the Derived objects are to be handled only by
the Derived* pointers. Could there be a better solution that I fail to
see? I need to use a polymorphic container because I have several
Derived* types. Thanks,

filimon
Well using reinterpret_cast would work, but the danger is simple. There
is no guarantee in this design that when you change the Base pointer
that you don't change it to point to an object of a different type,
therefore you run the risk of ending up with Derived1* pointing at an
object of type Derived2.

Whether this risk is worth running or whether you can't smarten up the
design somehow so it's intrinsically impossible is not a question I can
answer for you. But personally I would try and improve the design. Why
do you need to handle Derived pointers at all? Can't you use Base
pointers thoughtout. If you really need a Derived pointer then use
dynamic_cast to obtain it when you need it, rather than storing Derived
pointers in your data structures.

john
Mar 3 '07 #2

P: n/a
John Harrison wrote:
Filimon Roukoutakis wrote:
>Dear all,
assuming that through a mechanism, for example reflexion, the
Derived** is known explicitly. Would it be legal (and "moral") to do
this conversion by a cast (probably reinterpret would work here)? The
conversion is done for this purpose: I have an
std::map<std::string, Base*>. I want to "associate" Derived* handles
to the stored Base* so when Base* in the map changes (ie points
another address), the Derived* handle outside of the map is updated
automatically to point to the new address also. Actually what I do for
the moment is that I make the association using eg
Map.Associate(std::string name, Derived*&), where Map is a class
containing the mentioned std::map but I guess this is related to the
title of the post (Is Derived*& -Base*& moral?). This is the only
reason for the conversion, the Derived objects are to be handled only
by the Derived* pointers. Could there be a better solution that I fail
to see? I need to use a polymorphic container because I have several
Derived* types. Thanks,

filimon

Well using reinterpret_cast would work, but the danger is simple. There
is no guarantee in this design that when you change the Base pointer
that you don't change it to point to an object of a different type,
therefore you run the risk of ending up with Derived1* pointing at an
object of type Derived2.
This probably won't be possible. The stored objects are updated by an
internal procedure that assigns always the same Derived* (by name) on
the std::map. The type of the Derived* is associated with the name at
compile time, essentially what is done is that my users have this interface:
Derived1* t1=Produce<Derived>(name)
Derived2* t2=Produce<Derived2>(name)
....
Produce stores the objects in std::map<std::string, Base*>, with
key_val=name
In this sense, the name (which is used for lookup in std::map) is
statically bound to the type.

In another process, after the objects get serialized/deserialized, my
users use either map lookup or the "handles" we discuss to access the
objects.
>
Whether this risk is worth running or whether you can't smarten up the
design somehow so it's intrinsically impossible is not a question I can
answer for you. But personally I would try and improve the design. Why
do you need to handle Derived pointers at all? Can't you use Base
pointers thoughtout. If you really need a Derived pointer then use
dynamic_cast to obtain it when you need it, rather than storing Derived
pointers in your data structures.
The reason for not using Base pointers is that my Derived types have
different member functions. The only reason that they inherit from Base
is that I want to keep them in the same std::map (any other
options/suggestion would be helpful). In addition, I want the user to be
able to perform operations directly with the Derived* handles without
having necessarily to lookup the std::map. I assume that the solution
you suggest for dynamic cast essentially implies
dynamic_cast<Derived>(std::map::Find(name)->second)->Call
This could potentially hurt performance (I am talking about several
thousands of lookups per second).
Other solution would be to put all possible members as pure virtuals in
Base, but I would like to avoid this design because it would mean
essentially either throwing an exception when I do not want to allow an
operation for eg Derived1 but I want it for Derived2 or putting out a
message "Do not use this method with Derived1". I do not find these
solutions very good.
My question boils down to the following: If I absolutely know the type
of the Derived* throughout my code, so essentially eliminating the
reason for using it the wrong way, are there any other dangerous issues
about this cast (ie could memory alignment problems or something else I
cannot imagine come into play)?

filimon
>
john
Mar 3 '07 #3

P: n/a
Filimon Roukoutakis wrote:
John Harrison wrote:
>Filimon Roukoutakis wrote:
>>Dear all,
assuming that through a mechanism, for example reflexion, the
Derived** is known explicitly. Would it be legal (and "moral") to do
this conversion by a cast (probably reinterpret would work here)? The
conversion is done for this purpose: I have an
std::map<std::string, Base*>. I want to "associate" Derived* handles
to the stored Base* so when Base* in the map changes (ie points
another address), the Derived* handle outside of the map is updated
automatically to point to the new address also. Actually what I do
for the moment is that I make the association using eg
Map.Associate(std::string name, Derived*&), where Map is a class
containing the mentioned std::map but I guess this is related to the
title of the post (Is Derived*& -Base*& moral?). This is the only
reason for the conversion, the Derived objects are to be handled only
by the Derived* pointers. Could there be a better solution that I
fail to see? I need to use a polymorphic container because I have
several Derived* types. Thanks,

filimon


Well using reinterpret_cast would work, but the danger is simple.
There is no guarantee in this design that when you change the Base
pointer that you don't change it to point to an object of a different
type, therefore you run the risk of ending up with Derived1* pointing
at an object of type Derived2.


This probably won't be possible. The stored objects are updated by an
internal procedure that assigns always the same Derived* (by name) on
the std::map. The type of the Derived* is associated with the name at
compile time, essentially what is done is that my users have this
interface:
Derived1* t1=Produce<Derived>(name)
Derived2* t2=Produce<Derived2>(name)
...
Produce stores the objects in std::map<std::string, Base*>, with
key_val=name
In this sense, the name (which is used for lookup in std::map) is
statically bound to the type.

In another process, after the objects get serialized/deserialized, my
users use either map lookup or the "handles" we discuss to access the
objects.
>>
Whether this risk is worth running or whether you can't smarten up the
design somehow so it's intrinsically impossible is not a question I
can answer for you. But personally I would try and improve the design.
Why do you need to handle Derived pointers at all? Can't you use Base
pointers thoughtout. If you really need a Derived pointer then use
dynamic_cast to obtain it when you need it, rather than storing
Derived pointers in your data structures.


The reason for not using Base pointers is that my Derived types have
different member functions. The only reason that they inherit from Base
is that I want to keep them in the same std::map (any other
options/suggestion would be helpful).
Make a std::map of void* pointers. If your types are really unrelated
(as seems to be the case) then that would be more 'honest'.
In addition, I want the user to be
able to perform operations directly with the Derived* handles without
having necessarily to lookup the std::map. I assume that the solution
you suggest for dynamic cast essentially implies
dynamic_cast<Derived>(std::map::Find(name)->second)->Call
This could potentially hurt performance (I am talking about several
thousands of lookups per second).
Other solution would be to put all possible members as pure virtuals in
Base, but I would like to avoid this design because it would mean
essentially either throwing an exception when I do not want to allow an
operation for eg Derived1 but I want it for Derived2 or putting out a
message "Do not use this method with Derived1". I do not find these
solutions very good.
My question boils down to the following: If I absolutely know the type
of the Derived* throughout my code, so essentially eliminating the
reason for using it the wrong way, are there any other dangerous issues
about this cast (ie could memory alignment problems or something else I
cannot imagine come into play)?
No I don't see any problems. Multiple inheritence in one of your derived
classes could be a problem, but you can avoid even that by using void*
instead of Base*.

john
Mar 3 '07 #4

This discussion thread is closed

Replies have been disabled for this discussion.