There are four types of casts in C++, so C++ is not type-safe. It is: static_cast, dynamic_cast, const_cast, reinterpret_cast
Why using C-style casts can convert anything you want to a desirable type. Then why do you need a new C++ type cast?
New types of casting can provide better control over the casting process, allowing control of various types of casting. The style in C++ is static_cast<type>(content). The other benefit of C++ style casting is that they can make a clearer indication of what they are going to do. Programmers can immediately know the purpose of a cast by just a glance at such code.
The difference between four conversions:
static_cast:It can realize the mutual conversion between built-in basic data types in C++.
int c=static_cast<int>(7.987);
If a class is involved, static_cast can only be found inTypes of interconnectedconvert each other,Does not necessarily contain virtual functions。
class A
{};
class B:public A
{};
class C
{};
int main()
{
A* a=new A;
B* b;
C* c;
b=static_cast<B>(a); // Compilation will not report an error, Class B inherits Class A
c=static_cast<B>(a); // Compilation error, Class C has nothing to do with Class A
return 1;
}
const_cast:The const_cast operation cannot be converted between different types. Instead, it simply converts an expression it acts as a constant. It can convert a data that is not originally const type into a const type, or remove the const property.
reinterpret_cast:Has the same ability as C-style cast. It can convert any built-in data type to any other data type, or any pointer type to another type. It can even convert built-in data types into pointers without considering type safety or constants. It is absolutely not necessary unless it is absolutely necessary.
dynamic_cast:
(1) The other three types are completed at compile time. Dynamic_cast is processed at runtime and type checking is required during runtime.
(2) Cannot be used for casting of built-in basic data types.
(3) If the dynamic_cast conversion is successful, it returns a pointer or reference to the class, and if the conversion fails, it will return NULL.
(4) Use dynamic_cast to convert,There must be virtual functions in the base class, otherwise the compilation will not be passed.
The reason why there is a virtual function needs to be detected in B:The existence of virtual functions in the class means that it wants to make the base class pointer or reference point to the derived class object, and the conversion is only meaningful at this time.
This is because runtime type check requires runtime type information, and this information is stored in the virtual function table of the class (for the concept of virtual function table, see <Inside c++ object model> for details).
Only classes that define virtual functions have virtual function tables.
(5) When converting classes and uplink conversions between class levels, the effects of dynamic_cast and static_cast are the same. When performing downlink conversion, dynamic_cast has the function of type checking, which is safer than static_cast. Upconversion is a downconversion to a subclass object, that is, converting the parent class pointer into a subclass pointer. The success of downconversion is also related to the type to be converted, that is, the actual type of the object pointed to by the pointer to be converted must be the same as the object type after conversion, otherwise the conversion will fail.
Reference example:
#include<iostream>
#include<cstring>
using namespace std;
class A
{
public:
virtual void f()
{
cout<<"hello"<<endl;
};
};
class B:public A
{
public:
void f()
{
cout<<"hello2"<<endl;
};
};
class C
{
void pp()
{
return;
}
};
int fun()
{
return 1;
}
int main()
{
A* a1=new B;//a1 is a pointer of type A to point to an object of type B
A* a2=new A;//a2 is a pointer of type A pointer pointing to an object of type A
B* b;
C* c;
b=dynamic_cast<B*>(a1);//The result is not null, and the down conversion is successful. A1 points to an object of type B, so it can be converted into a pointer of type B.
if(b==NULL)
{
cout<<"null"<<endl;
}
else
{
cout<<"not null"<<endl;
}
b=dynamic_cast<B*>(a2);//The result is null, down conversion failed
if(b==NULL)
{
cout<<"null"<<endl;
}
else
{
cout<<"not null"<<endl;
}
c=dynamic_cast<C*>(a);//The result is null, down conversion failed
if(c==NULL)
{
cout<<"null"<<endl;
}
else
{
cout<<"not null"<<endl;
}
delete(a);
return 0;
}
Why using C-style casts can convert anything you want to a desirable type. Then why do you need a new C++ type cast?
New types of casting can provide better control over the casting process, allowing control of various types of casting. The style in C++ is static_cast<type>(content). The other benefit of C++ style casting is that they can make a clearer indication of what they are going to do. Programmers can immediately know the purpose of a cast by just a glance at such code.
The difference between four conversions:
static_cast:It can realize the mutual conversion between built-in basic data types in C++.
Copy the codeThe code is as follows:
int c=static_cast<int>(7.987);
If a class is involved, static_cast can only be found inTypes of interconnectedconvert each other,Does not necessarily contain virtual functions。
Copy the codeThe code is as follows:
class A
{};
class B:public A
{};
class C
{};
int main()
{
A* a=new A;
B* b;
C* c;
b=static_cast<B>(a); // Compilation will not report an error, Class B inherits Class A
c=static_cast<B>(a); // Compilation error, Class C has nothing to do with Class A
return 1;
}
const_cast:The const_cast operation cannot be converted between different types. Instead, it simply converts an expression it acts as a constant. It can convert a data that is not originally const type into a const type, or remove the const property.
reinterpret_cast:Has the same ability as C-style cast. It can convert any built-in data type to any other data type, or any pointer type to another type. It can even convert built-in data types into pointers without considering type safety or constants. It is absolutely not necessary unless it is absolutely necessary.
dynamic_cast:
(1) The other three types are completed at compile time. Dynamic_cast is processed at runtime and type checking is required during runtime.
(2) Cannot be used for casting of built-in basic data types.
(3) If the dynamic_cast conversion is successful, it returns a pointer or reference to the class, and if the conversion fails, it will return NULL.
(4) Use dynamic_cast to convert,There must be virtual functions in the base class, otherwise the compilation will not be passed.
The reason why there is a virtual function needs to be detected in B:The existence of virtual functions in the class means that it wants to make the base class pointer or reference point to the derived class object, and the conversion is only meaningful at this time.
This is because runtime type check requires runtime type information, and this information is stored in the virtual function table of the class (for the concept of virtual function table, see <Inside c++ object model> for details).
Only classes that define virtual functions have virtual function tables.
(5) When converting classes and uplink conversions between class levels, the effects of dynamic_cast and static_cast are the same. When performing downlink conversion, dynamic_cast has the function of type checking, which is safer than static_cast. Upconversion is a downconversion to a subclass object, that is, converting the parent class pointer into a subclass pointer. The success of downconversion is also related to the type to be converted, that is, the actual type of the object pointed to by the pointer to be converted must be the same as the object type after conversion, otherwise the conversion will fail.
Reference example:
Copy the codeThe code is as follows:
#include<iostream>
#include<cstring>
using namespace std;
class A
{
public:
virtual void f()
{
cout<<"hello"<<endl;
};
};
class B:public A
{
public:
void f()
{
cout<<"hello2"<<endl;
};
};
class C
{
void pp()
{
return;
}
};
int fun()
{
return 1;
}
int main()
{
A* a1=new B;//a1 is a pointer of type A to point to an object of type B
A* a2=new A;//a2 is a pointer of type A pointer pointing to an object of type A
B* b;
C* c;
b=dynamic_cast<B*>(a1);//The result is not null, and the down conversion is successful. A1 points to an object of type B, so it can be converted into a pointer of type B.
if(b==NULL)
{
cout<<"null"<<endl;
}
else
{
cout<<"not null"<<endl;
}
b=dynamic_cast<B*>(a2);//The result is null, down conversion failed
if(b==NULL)
{
cout<<"null"<<endl;
}
else
{
cout<<"not null"<<endl;
}
c=dynamic_cast<C*>(a);//The result is null, down conversion failed
if(c==NULL)
{
cout<<"null"<<endl;
}
else
{
cout<<"not null"<<endl;
}
delete(a);
return 0;
}