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
AtoBdoesn'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
Bto be cast toB. E. g.:What you did will fail at runtime as soon as you try to access some data or method of
Bthat 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_castuses RTTI (run-time type information) to validate the operation and will throw anstd::bad_castexception if the conversion is not valid. This is unlikedynamic_casting pointers, in which case the cast returnsnullptrinstead of throwing an exception.