c++ casting issues

F

foothompson

I have a few questions regarding casting in C++.

let's take as an example:

class A
{
virtual foo();
};

class B
{
virtual bar();
};

class C: public A, public B
{
};

Is it ok to convert a Derived Class instance to a void * and back to
a base class?

For e.g. is it ok to perform the following sequence of steps?

C* c = new C();
void* p = static_cast<void *>(c);
B* b = static_cast<B*>(p);

If not, what is the proper sequence of steps needed to convert a
derived instance to a void * and then back to a base class?

Also, is it ok to compare pointers of a derived class and a base class
for equality? i.e is the following function guaranteed to work?

bool IsEqual(B* b, C* c)
{
return (b == c);
}

Thanks
 
V

Victor Bazarov

I have a few questions regarding casting in C++.

let's take as an example:

class A
{
virtual foo();
};

class B
{
virtual bar();
};

class C: public A, public B
{
};

Is it ok to convert a Derived Class instance to a void * and back to
a base class?

Why do you call it "back to a base class"? Why "back"?
For e.g. is it ok to perform the following sequence of steps?

C* c = new C();
void* p = static_cast<void *>(c);
B* b = static_cast<B*>(p);

If not, what is the proper sequence of steps needed to convert a
derived instance to a void * and then back to a base class?

The 'void*' needs to be converted back to the exact type it was obtained
from, i.e. the derived class, and then the pointer to derived converts
to a pointer to base implicitly.
Also, is it ok to compare pointers of a derived class and a base class
for equality? i.e is the following function guaranteed to work?

bool IsEqual(B* b, C* c)
{
return (b == c);
}

Not sure what you mean by "guaranteed to work" here. You don't show
how you would _call_ that function. Generally speaking, to be compaerd
two pointers have to point to the same type. There is an implicit
conversion of a ponter to derived to a pointer to base class. So, if
'C' derives from 'B', then 'c' will be converted to 'B*', and then the
two pointers will be compared.

V
 
J

Juha Nieminen

Is it ok to convert a Derived Class instance to a void * and back to
a base class?

No, because casting may actually change the value of the pointer (ie.
make it point to a different location than the original). Obviously if
you make a cast to void* in between, you lose this feature, and the
result will probably crash or misbehave in other ways (if the value
change was necessary).
If not, what is the proper sequence of steps needed to convert a
derived instance to a void * and then back to a base class?

Don't use void* at all. You are only asking for problems.

The only way to do it would be to cast the void* back to the original
derived type and then to the base class type. However, I assume that you
can't know what was the original derived type at the place where you
need this cast, so I think it's just not possible.
Also, is it ok to compare pointers of a derived class and a base class
for equality? i.e is the following function guaranteed to work?

bool IsEqual(B* b, C* c)
{
return (b == c);
}

Never thought of that before (so this is just IMO). If that compiles
(which I haven't tried), there's probably an implicit cast from the
derived type pointer to the base type pointer, so it might work.
 
C

Christopher

(e-mail address removed) wrote:
Don't use void* at all. You are only asking for problems.

I disagree. Sometimes it is now avoidable to use a void *, especially
when using the Windows API as they force you to in some of thier
function calls. It is often necessary to use void * and a
reinterpret_cast to and from. It is frowned upon and should be avoided
_if possible_. Your compiler will also warn you if it is worth its
salt, and rightfully so.
 
J

James Kanze

I disagree. Sometimes it is now avoidable to use a void *,
especially when using the Windows API as they force you to in
some of thier function calls.

Not just Windows. A lot of the Posix API uses void* as well.
Whenever there is a callback in a C API, it is traditional to
add void* for user data---typically, in C++, this will be a
pointer to a class, and the `extern "C"' function which we pass
to the callback will convert the pointer back to the class
type, and call a member function on it.

In such cases, it is very, very important to explicitly cast the
actual pointer to the type used in the callback function before
passing it. A typical scenario might be (using pthread_create,
from the Posix interface):

extern "C" void* threadStarter( void* p )
{
return static_cast< ThreadBase* >( p )->run() ;
}

// ...

class MyThread : public ThreadBase
{
// ...
} ;

// ...
MyThread newThread ;
pthread_create( &threadId, NULL, threadStarter,
static_cast< ThreadBase* >( &newThread ) ) ;

Without the static_cast in the call, the code has undefined
behavior. (In this particular case, of course, and even better
solution would be to use boost::threads:). But it serves as a
good example.)
It is often necessary to use void * and a reinterpret_cast to
and from.

Not reinterpret_cast, static_cast.
It is frowned upon and should be avoided _if possible_.

Obviously, if you don't have a choice, you don't have a choice.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top