简体   繁体   中英

Why is only static_cast able to return new object of requested type?

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
}

Only static_cast is able to return an object of desirable type

This is incorrect. All casts return an object when the cast target is an object type.

That said:

  • const_cast target can only be a reference, pointer to object or pointer to member. This is because other types aren't compound types whose "inner" type's cv-qualifiers could be modified.
  • dynamic_cast target can only be a reference or a pointer to object. You cannot have polymorphism without indirection. References and pointers are the forms of indirection that exist in C++.

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 behavior 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 .

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 behavior 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 would result with sliced out Gun sub-object of MachineGun tt assigned to newGun1 and that is usually programming error. What you tried to achieve with cast remains totally dark however.

Maybe the short answer is that static_cast can take a type with no reference (and no pointer) because it is the only cast that can invoke a constructor of the target type.

Please correct me if I am wrong.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM