Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ cast to derived class

How can i cast to a derived class? The below approaches all give the following error:

Cannot convert from BaseType to DerivedType. No constructor could take the source type, or constructor overload resolution was ambiguous.

BaseType m_baseType;  DerivedType m_derivedType = m_baseType; // gives same error  DerivedType m_derivedType = (DerivedType)m_baseType; // gives same error  DerivedType * m_derivedType = (DerivedType*) & m_baseType; // gives same error 
like image 259
user346443 Avatar asked Mar 15 '11 14:03

user346443


People also ask

Can you cast from base class to derived?

No, there is no built in conversion for this. You'll need to create a constructor, like you mentioned, or some other conversion method. Also, since BaseClass is not a DerivedClass, myDerivedObject will be null, andd the last line above will throw a null ref exception.

Can you cast a base class to a derived class in C++?

C++ Explicit type conversions Base to derived conversion Likewise, a reference to base class can be converted to a reference to derived class using static_cast . If the source type is polymorphic, dynamic_cast can be used to perform a base to derived conversion.

What is Upcasting in C?

It is the process to create the derived class's pointer or reference from the base class's pointer or reference, and the process is called Upcasting. It means the upcasting used to convert the reference or pointer of the derived class to a base class.

What is the use of Upcasting and downcasting in C++?

Upcasting can cause object slicing when a derived class object is passed by value as a base class object, as in foo(Base derived_obj). The opposite process, converting a base-class pointer (reference) to a derived-class pointer (reference) is called downcasting. Downcasting is not allowed without an explicit type cast.


2 Answers

Think like this:

class Animal { /* Some virtual members */ }; class Dog: public Animal {}; class Cat: public Animal {};   Dog     dog; Cat     cat; Animal& AnimalRef1 = dog;  // Notice no cast required. (Dogs and cats are animals). Animal& AnimalRef2 = cat; Animal* AnimalPtr1 = &dog; Animal* AnimlaPtr2 = &cat;  Cat&    catRef1 = dynamic_cast<Cat&>(AnimalRef1);  // Throws an exception  AnimalRef1 is a dog Cat*    catPtr1 = dynamic_cast<Cat*>(AnimalPtr1);  // Returns NULL         AnimalPtr1 is a dog Cat&    catRef2 = dynamic_cast<Cat&>(AnimalRef2);  // Works Cat*    catPtr2 = dynamic_cast<Cat*>(AnimalPtr2);  // Works  // This on the other hand makes no sense // An animal object is not a cat. Therefore it can not be treated like a Cat. Animal  a; Cat&    catRef1 = dynamic_cast<Cat&>(a);    // Throws an exception  Its not a CAT Cat*    catPtr1 = dynamic_cast<Cat*>(&a);   // Returns NULL         Its not a CAT. 

Now looking back at your first statement:

Animal   animal = cat;    // This works. But it slices the cat part out and just                           // assigns the animal part of the object. Cat      bigCat = animal; // Makes no sense.                           // An animal is not a cat!!!!! Dog      bigDog = bigCat; // A cat is not a dog !!!! 

You should very rarely ever need to use dynamic cast.
This is why we have virtual methods:

void makeNoise(Animal& animal) {      animal.DoNoiseMake(); }  Dog    dog; Cat    cat; Duck   duck; Chicken chicken;  makeNoise(dog); makeNoise(cat); makeNoise(duck); makeNoise(chicken); 

The only reason I can think of is if you stored your object in a base class container:

std::vector<Animal*>  barnYard; barnYard.push_back(&dog); barnYard.push_back(&cat); barnYard.push_back(&duck); barnYard.push_back(&chicken);  Dog*  dog = dynamic_cast<Dog*>(barnYard[1]); // Note: NULL as this was the cat. 

But if you need to cast particular objects back to Dogs then there is a fundamental problem in your design. You should be accessing properties via the virtual methods.

barnYard[1]->DoNoiseMake(); 
like image 166
Martin York Avatar answered Sep 27 '22 17:09

Martin York


dynamic_cast should be what you are looking for.

EDIT:

DerivedType m_derivedType = m_baseType; // gives same error 

The above appears to be trying to invoke the assignment operator, which is probably not defined on type DerivedType and accepting a type of BaseType.

DerivedType * m_derivedType = (DerivedType*) & m_baseType; // gives same error 

You are on the right path here but the usage of the dynamic_cast will attempt to safely cast to the supplied type and if it fails, a NULL will be returned.

Going on memory here, try this (but note the cast will return NULL as you are casting from a base type to a derived type):

DerivedType * m_derivedType = dynamic_cast<DerivedType*>(&m_baseType); 

If m_baseType was a pointer and actually pointed to a type of DerivedType, then the dynamic_cast should work.

Hope this helps!

like image 44
Michael Avatar answered Sep 27 '22 16:09

Michael