Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++
Hi, what is the best way to cast one object to another? (no pointers).
 
e.g., I have a function:
 
void app:f(ClassA object)
{
 
ClassB object2 = (ClassB) object;
}
 
would this work? We can assume ClassB is derived from ClassA.
 
thanks.
Posted 25-Feb-13 0:39am
Comments
Philippe Mori at 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?
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

If ClassB derives ClassA, then you should do;
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
  Permalink  
v3
Comments
Stefan_Lang at 25-Feb-13 6:06am
   
The right way, but the wrong types: dynamic_cast can only be used on references and pointers.
Fredrik Bornander at 25-Feb-13 6:22am
   
Right you are.
Philippe Mori at 27-Feb-13 19:10pm
   
You also need a reference on object2 otherwise you would have new object...
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Matra Divat wrote:
We can assume ClassB is derived from ClassA.

In that case fix the function prototype:
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:
 
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 ...
   }
}
  Permalink  
v5
Comments
Matra Divat at 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 at 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!)
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

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.
  Permalink  
Comments
Stefan_Lang at 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 at 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 at 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 at 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 at 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.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 4

union AB {
ClassA object;
ClassB object2;
};
void app::f(ClassA object) {
AB objectab;
objectab.object = object;
ClassB object2 = objectab.object2;
}
  Permalink  
Comments
Philippe Mori at 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)

  Print Answers RSS
0 Sergey Alexandrovich Kryukov 535
1 Kornfeld Eliyahu Peter 407
2 Maciej Los 369
3 DamithSL 221
4 OriginalGriff 218
0 OriginalGriff 6,353
1 DamithSL 4,854
2 Maciej Los 4,476
3 Kornfeld Eliyahu Peter 4,058
4 Sergey Alexandrovich Kryukov 3,917


Advertise | Privacy | Mobile
Web01 | 2.8.141223.1 | Last Updated 27 Feb 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100