Among static_cast, dynamic_cast, reinterpret_cast and const_cast, only static_cast is able to return an object of desirable type, whereas the other type can return only pointer or reference to representation. Why is it so?
Examples:
int y = 3;
double z = reinterpret_cast<double> (y);//error
double z = reinterpret_cast<double&> (y);//ok
double z = static_cast<double> (y);//but this is ok!!!
const int y = 3;
int z = const_cast<int> (y);//error
int z = const_cast<int&> (y);//ok
and for dynamic_cast:
using namespace std;
class Gun
{
public:
virtual void shoot(){
cout << "BANG!\n";
}
};
class MachineGun : public Gun{
public:
void shoot() override{
cout <<"3X-BANG\n";
}
};
int main()
{
Gun gun;
MachineGun tt;
Gun* gunp = &gun;
Gun* gunp1 = &tt;
Gun* newGun = dynamic_cast<Gun*>(gunp1);//ok
Gun newGun1 = dynamic_cast<Gun>(tt);//error
}
I'm making attempt to explain based on example, as addition to other answer that did explain nature of casts.
int y = 3;
double z = reinterpret_cast<double> (y);//error
This is not one of 11 allowed casts with reinterpret_cast
. Also std::bit_cast
can't cast it on most platforms as the int
typically does not have enough bits for double
. So it is unsure what you wanted to achieve.
double z = reinterpret_cast<double&> (y);//ok
This is present in list of valid reinterpret_cast
but likely causes undefined behaviour for same reason why std::bit_cast
refuses. In typical implementation your z
is bigger than y
and so takes bits beyond memory location of y
. In such places prefer std::bit_cast
that does not compile to undefined behaviour but refuses to compile.
double z = static_cast<double> (y);//but this is ok!!!
But that is fully valid. It is effectively same as
double z = y;
Compilers do not even warn about the latter. However when the value range of y
does not fully fit to z
then it is not clear if it was intentional. On such cases it is better to use former to indicate intent.
const int y = 3;
int z = const_cast<int> (y);//error
That is good. Absurd const_cast
does not compile! Or how does the effect that you tried to achieve differ from lot more readable
int z = y;
I would write that. Please describe the situation where you would write former.
int z = const_cast<int&> (y);//ok
Works, but is similarly unneeded and confusing like previous. I would only use const_cast
for situations like that:
int x;
const int& y = x;
int& z = const_cast<int&> (y);
z = 42;
Here I know that thing referred by reference to const y
is really not const originally and so it is not undefined behaviour to modify it to 42
.
About dynamic_cast
your example does not make sense at all what it wants to do:
Gun newGun1 = dynamic_cast<Gun>(tt);//error
It could be perhaps trying to do something like that:
Gun newGun1 = tt;
That compiles. However that results with newGun1
initialised with sliced out Gun
base sub-object of MachineGun tt
and that is often programming error. What you tried to achieve with cast remains totally dark however.