Re: stroustrup, void*, and reinterpret_cast
andrew_nuss@yahoo.com wrote:
It can get pretty complex for me, namely I also want to store 2 types
of pointers in a virtual hierarchy as void* and then retrieve it and
narrow it to the base class pointer.
Possibly a not very C++ way to approach the problem. Is this time
critical? If not, you could provide a virtual "getPointer()" method
(please choose a better name) in the base class that returns the common
base of the two objects, and use covariance to specialize this method in
the derived classes. Alternatively, use a container that is templated to
the class you want to store in.
The question in the following
hierarchy of widening to an interface from 2 different derivations, and
then further widening to void*, and then being able to narrow back from
void* to the interface, what's better than my use of
reinterpret_cast<>.
class Arc;
struct ArcLink {
virtual Arc* ThisArc () = 0;
virtual ArcLink* NextLink () = 0;
};
class Arc : public ArcLink {
... some data members
public:
virtual Arc* ThisArc () { return this; }
virtual ArcLink* NextLink() { return 0; }
... additional functionality
};
class ArcLinkImpl : public ArcLink {
Arc* arc;
ArcLink* tail;
public:
virtual Arc* ThisArc () { return arc; }
virtual ArcLink* NextLink () { return tail; }
};
// from utilities for a red-black set
struct IntSetElem {
void* obj;
private:
IntSetElem* left;
IntSetElem* right;
int key;
bool color;
};
This should probably be a template where the templare parameter
describes the object pointed to. Alternatively, why not use an
already available container from the STL or Boost? Which kind of
operations do you need for IntSetElem?
// and the question is, what casts to and from elem->obj
main () {
IntSetElem* elem1 = ...; // get an element from a set
IntSetElem* elem2 = ...; // get another
Arc* arc = ...; // create an arc
ArcLinkImpl* arclink = ...; // create an arclink
ArcLink* intf = arc; // widen
elem1->obj = reinterpret_cast<void*>(intf);
//??? can I pass arc directly to the cast here
No cast is needed here, though maybe you would like to use an
IntSetElem<ArcLink> here?
intf = arclink; // a different widen
This works.
elem2->obj = reinterpret_cast<void*>(intf);
//??? can I pass arclink directly to the cast here
No cast required. Every pointer can be converted to a void *
without a cast.
// now fetch Arc* as ArcLink*
intf = reinterpret_cast<ArcLink*>(elem1->obj);
Bad idea. Either use the template idea, or use a static_cast<>.
You do not care about the "raw bit pattern" of the pointer here. What
you want to tell the compiler is to narrow the pointer to a more
specific object.
// I bet this is ok because I made sure to stuff it
// as an ArcLink* interface pointer
// what's better???
To use an already available container, likely.
// now fetch ArcLinkImpl* as ArcLink*
intf = reinterpret_cast<ArcLink*>(elem2->obj);
// again ok because I stuffed the ArcLinkImpl*
// as an ArcLink*
// what's better???
No cast at all if you can avoid it. If elem2 would be an
IntSetElem<ArcLink> and would be declared as follows:
template<class T>
struct IntSetElem {
T* obj;
private:
IntSetElem* left;
IntSetElem* right;
int key;
bool color;
};
no cast whatsoever would be required, and type-correctness would
be guaranteed by the compiler.
By the way: Why is this a struct? And are you sure the compiler
generated copy and assignment operators are what you want?
So long,
Thomas
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]