Precisely, why does B b = (B&) a
compile and work whereas B b = (B) a
does not in the below program?
#include <iostream>
using namespace std;
class A {public: void f(){ cout<<"A"<<endl;} };
class B : public A { public: void f(){cout<<"B"<<endl;} };
void g(A a){ B b = (B&) a; b.f(); }
int main() {
B b; g(b);
return 0;
}
Is there something about casting to a derived type with reference that I am missing here ? If I just cast to B, it gives a compile time error that the constructor B(A a) does not exist.
Because the implicit conversion from
A
toB
doesn't exist, and you didn't define an explicit one either.Reference casting, on the other hand, is valid because it is allowed for inherited types. More precisely, you can cast both ways between different classes in the same inheritance hierarchy. Same goes for pointers. The related concept is called polymorphism, if you'd like some pointers for further study.
Do note, however, that it only makes sense for an object that is of type
B
to be cast toB
. E. g.:What you did will fail at runtime as soon as you try to access some data or method of
B
that does not exist inA
. Because your actual object isA
, notB
.Upcasting (from an descendant to an ascendant) is always safe because any object of a class that inherits the base class is a valid base object. The downcasting, however, is dangerous for the exact reason I explained above, and should never be done using a C-style cast. Instead, use
dynamic_cast
:dynamic_cast
uses RTTI (run-time type information) to validate the operation and will throw anstd::bad_cast
exception if the conversion is not valid. This is unlikedynamic_cast
ing pointers, in which case the cast returnsnullptr
instead of throwing an exception.