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
|