84

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 
7
  • 11
    I don't believe the last one gives the same error. Commented Mar 15, 2011 at 14:37
  • 3
    Are you sure your DerivedType is inheriting from BaseType. Can you post more code? Commented Mar 15, 2011 at 14:38
  • 4
    If you have any background in languages in C# or Java, you should note that dynamic type information is only really used when you have pointers (e.g. BaseType *b = new DerivedType()). Otherwise, you'll end up with slicing. Commented Mar 15, 2011 at 14:44
  • For a start you should not be doing that anyway. Which is why you are getting errors. When done correctly (via dynamic_cast) the result should either be NULL or an exception. What are you really trying to do? Commented Mar 15, 2011 at 14:53
  • 2
    You just can't do that, because the BaseType isn't a DerivedType. You cannot cast an Animal to be Dog, but perhaps a Dog* into an Animal*. Commented Mar 15, 2011 at 14:57

4 Answers 4

202

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(); 
Sign up to request clarification or add additional context in comments.

9 Comments

So a function like HerdAllTheCats(barnYard) makes no sense and shouldn't be done? ShaveTheShaveable(barnYard) would be right out of the question? (obviously C++ would make that very hard to do, but it's a common use of OOP)
@CodeAbominator If all animals were Shaveable then a ShaveTheShaveable() function seems pretty reasonable. But if only Cats were shavable then no it does not sound reasonable not OOP. But this is way to abstract a discussion. You should ask a question and get feedback.
I'd point out that without defining the body of these classes the above example is a bit dangerous, the inheritance by itself does not guarantee that your classes are going to be polymorphic. And dynamic_cast only works with polymorphic classes, which means Animal must contain at least one virtual member function (as a minimum a virtual destructor). Without that you will get the following error from the compiler: "the operand of a runtime dynamic_cast must have a polymorphic class type". Also see here: stackoverflow.com/questions/23089511/…
why would the use of dynamic_cast be rare and how come casting the derived to parent be a fundamental design problem?
@niken: To be a polymorphic type the base class must have virtual functions (Above I added comment: /* Some virtual members */ but you need a least one. But this can be the destructor).
|
14

You can't cast a base object to a derived type - it isn't of that type.

If you have a base type pointer to a derived object, then you can cast that pointer around using dynamic_cast. For instance:

DerivedType D; BaseType B; BaseType *B_ptr=&B BaseType *D_ptr=&D;// get a base pointer to derived type DerivedType *derived_ptr1=dynamic_cast<DerivedType*>(D_ptr);// works fine DerivedType *derived_ptr2=dynamic_cast<DerivedType*>(B_ptr);// returns NULL 

Comments

11

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!

3 Comments

This smells of a lack of default constructors for each of the types. This might be at the issue when attempting to cast and receiving the noted error.
The first line is not trying to invoke the assignment operator. It is trying to convert m_baseType to type DerivedType, then copy that using the copy constructor.
There is no copy constructor call in the first line. If anything, the default constructor of the DerivedType would be invoked, followed by an attempt to invoke an assignment operator, if one existed with the BaseType as the argument.
3

First of all - prerequisite for downcast is that object you are casting is of the type you are casting to. Casting with dynamic_cast will check this condition in runtime (provided that casted object has some virtual functions) and throw bad_cast or return NULL pointer on failure. Compile-time casts will not check anything and will just lead tu undefined behaviour if this prerequisite does not hold.
Now analyzing your code:

DerivedType m_derivedType = m_baseType; 

Here there is no casting. You are creating a new object of type DerivedType and try to initialize it with value of m_baseType variable.

Next line is not much better:

DerivedType m_derivedType = (DerivedType)m_baseType; 

Here you are creating a temporary of DerivedType type initialized with m_baseType value.

The last line

DerivedType * m_derivedType = (DerivedType*) & m_baseType; 

should compile provided that BaseType is a direct or indirect public base class of DerivedType. It has two flaws anyway:

  1. You use deprecated C-style cast. The proper way for such casts is
    static_cast<DerivedType *>(&m_baseType)
  2. The actual type of casted object is not of DerivedType (as it was defined as BaseType m_baseType; so any use of m_derivedType pointer will result in undefined behaviour.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.