Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Question on c++ faq 21.2 Derived** -> Base**

Reply
Thread Tools

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

 
 
Filimon Roukoutakis
Guest
Posts: n/a
 
      03-03-2007
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
 
Reply With Quote
 
 
 
 
John Harrison
Guest
Posts: n/a
 
      03-03-2007
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
 
Reply With Quote
 
 
 
 
Filimon Roukoutakis
Guest
Posts: n/a
 
      03-03-2007
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

 
Reply With Quote
 
John Harrison
Guest
Posts: n/a
 
      03-03-2007
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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
FAQ or not FAQ? =?ISO-8859-15?Q?Juli=E1n?= Albo C++ 28 01-15-2007 04:33 AM
FAQ/FAQ notes site makeover Peter Michaux Javascript 22 11-27-2006 01:55 AM
FAQ - How do I direct someone to this FAQ? FAQ server Javascript 1 08-04-2006 10:13 PM
[de] Update of FAQ in German/FAQ auf Deutsch ueberarbeitet Josef 'Jupp' Schugt Ruby 0 09-22-2003 08:56 PM
Question about Memory Pool Example in C++ Faq Philip Lawatsch C++ 9 07-09-2003 04:44 PM



Advertisments