Click here to Skip to main content
15,896,348 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi, what is the best way to cast one object to another? (no pointers).

e.g., I have a function:

C++
void app:f(ClassA object)
{

ClassB object2 = (ClassB) object;
}


would this work? We can assume ClassB is derived from ClassA.

thanks.
Posted
Comments
Philippe Mori 27-Feb-13 19:14pm    
Do you want a new object or the same object interpreted differently?

Do you wants to assume that the object is of type ClassB or verify it?

If ClassB derives ClassA, then you should do;
C++
ClassB object2 = *dynamic_cast<ClassB*>(&object);


But you don't want to do that. Pass references and cast them using dynamic_cast without the referencing and dereferencing instead.
Fredrik
 
Share this answer
 
v3
Comments
Stefan_Lang 25-Feb-13 6:06am    
The right way, but the wrong types: dynamic_cast can only be used on references and pointers.
Fredrik Bornander 25-Feb-13 6:22am    
Right you are.
Philippe Mori 27-Feb-13 19:10pm    
You also need a reference on object2 otherwise you would have new object...
Matra Divat wrote:
We can assume ClassB is derived from ClassA.

In that case fix the function prototype:
C++
void app::f(ClassB b) {
   // ...
}

Casting a type is always a consequence of inappropriate interface design. If you have the ability to fix the interface, do that before having to introduce type casts!

If for any reason you cannot avoid the cast, the safe and correct way is not to assume, but to verify. Doing so is possible using dynamic_cast[^], but this cast only works on pointers and references. In your case, you should be doing sth like this:

C++
class ClassA {
   // ...
};
class ClassB : public class ClassA {
   // ...
};

void app::f(ClassA a) // 'a' is passed by value - is that intended?
{
   ClassB* pb = dynamic_cast<ClassB*>(&object);
   assert (0 != pb);  // verify your assumption - pointer will be NULL on failure
   if (0 == pb) {
      // this code will only be processed in release mode
      // issue an error message or throw an exception
   }
   else {
      ClassB& b = *pb;        // using reference to memory location of a
      // continue using your converted object ...
   }
}
 
Share this answer
 
v5
Comments
[no name] 25-Feb-13 7:11am    
instead of "a" it should be "object" right in your code? ps. yes I am casting one object to another (no pointers)
Stefan_Lang 25-Feb-13 8:00am    
Yes, I changed 'object' to 'a' because in my initial response the use of that name caused some confusion. I rewrote it but forgot to change it back. :-)

My remark on pointers was due to the restriction of dynamic_cast, but my code shows how to use it anyway.

My comment in the code ('a' is passed by value) referes to the fact that you're working on a local copy, rather than the original object, which may or may not be intended.

In any case, dynamic_cast returns a pointer, and that pointer will be 0 if your assumption turns out to be false. Deal with that possibility however seems appropriate to you.

The cast you suggested will be accepted by the compiler, and may even work under certain conditions, but more likely, your application will crash because of important differences in the memory layout of the two classes. Most important of all, if the two classes posses virtual functions, then the virtual function tables will not be mapped correctly. (OTOH, if you have no virtual functions, then you shouldn't be using inheritance to start with!)
void app:f(ClassA object)
{
 
ClassB object2 = (ClassB) object;
}


This won't do a cast (in C++). The syntax used in your question looks a lot like something that came from some java code (or C#?).

Study the difference between "ClassA" and "ClassA*". Likewise "ClassB" and "ClassB*".

You might have more success with the following:

void app:f(ClassA* object)
{
 
ClassB* object2 = (ClassB*) object;
}


but there are a lot of ways to go off the tracks with this too.
 
Share this answer
 
Comments
Stefan_Lang 26-Feb-13 8:48am    
Actually the cast will work - at least it will compile. It is a C-style cast and will simply reinterpret the memory. You'd have the same effect (without cast) if you define a union:

union AB {
ClassA object;
ClassB object2;
};
void app::f(ClassA object) {
AB objectab;
objectab.object = object;
ClassB object2 = objectab.object2;
}
H.Brydon 26-Feb-13 11:32am    
You say "Actually the cast will work" - actually no - you are not doing a cast. If your code looks like:

void app:f(ClassA object)
{
ClassB object2 = (ClassB) object;
}

the "(ClassB)" does not do a cast. What happens is that 'object' is copied to a temporary "ClassB" object (shallow copy in this case) and assigned to 'object2'. There is no cast. Your union example is wrong. The objects are different. In C++, they are not given the same address (as they would in a union). Objects 'object' and 'object2' are distinct, where 'object2' is a shallow copy of 'object'.

If you did something similar in java, then object2 would be an alias of object. Not in C++.
Stefan_Lang 27-Feb-13 4:12am    
Ok, it seems I've confused this with reinterpret_cast. I remembered code that did similar casts, and therefore assumed it must work the same way,

However, I just tried and the cast indeed only works the other way round (from ClassB to ClassA in this case).

Obviously the union example is not a good one then, given the fact the 'cast' wouldn't even compile. Sorry for the confusion.
H.Brydon 27-Feb-13 9:46am    
No, it didn't work. Either way around. Look at the difference between the following 2 statements:

ClassB object2 = (ClassB) object;
ClassB* pObject2 = (ClassB*) pObject;

The first is not a cast no matter what the objects are. It is a shallow copy (usually, depending on the class definition).
Stefan_Lang 27-Feb-13 10:03am    
For me, a "cast" is whatever the compiler makes of a cast statement. If your definition is different, then we're talking apples and oranges. Anyway, I don't see any remaining disagreements.
union AB {
ClassA object;
ClassB object2;
};
void app::f(ClassA object) {
AB objectab;
objectab.object = object;
ClassB object2 = objectab.object2;
}
 
Share this answer
 
Comments
Philippe Mori 27-Feb-13 19:15pm    
Why not use reinterpret_cast if you want to pretent that the object is an unrelated type (or static_cast if typoes are related).

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900