conversion constructor
1. Converting other types to the current class type requires the help of the conversion constructor.
For specific examples: click
type conversion function
1. Convert the current class type to another type, which can only appear in a class.
2. Syntax format:
operator type(){ //TODO: return data; }
operator is a C++ keyword, type is the target type to be converted, and data is the data of type type to be returned.
Let's talk about conversion constructors and type conversion functions again (example)
The essence of type conversion
Four Type Conversion Operators
static_cast dynamic_cast const _cast和reinterpret_cast
keywords | illustrate |
---|---|
static_cast | It is used for benign conversion, generally does not cause accidental occurrence, and the risk is very low. |
const_cast | Used for conversions between const and non-const, volatile and non-volatile. |
reinterpret_cast | A highly dangerous conversion, which is just a reinterpretation of the binary bits, and does not adjust the data with the help of existing conversion rules, but can achieve the most flexible C++ type conversion. |
dynamic_cast | With RTTI, for type-safe downcasting (Downcasting). |
static_cast keyword
1. static_cast can only be used for benign conversion, such conversion risk is low, and generally no accidents will occur, for example:
- The original automatic type conversion, such as short to int, int to double, const to non-const, upcasting, etc.;
- Conversion between void pointer and concrete type pointer, such as
void *
transferint *
,char *
transfervoid *
, etc.; - Conversion between a class with a conversion constructor or type conversion function and other types, such as double to Complex (calling the conversion constructor), Complex to double (calling the type conversion function).
It should be noted that static_cast cannot be used to convert between unrelated types, because these conversions are risky, for example:
- Conversion between two concrete type pointers, such as
int *
turndouble *
,Student *
turnint *
, etc. Different types of data have different storage formats and lengths. After using a pointer of type A to point to data of type B, the data will be processed in the way of type A: if it is a read operation, you may get a bunch of meaningless data. value; if it is a write operation, the data of type B may be corrupted, and when the data is read in the way of type B again, you will get a bunch of meaningless values. - Conversion between int and pointer. It is very dangerous to assign a specific address to a pointer variable, because the memory at this address may not be allocated, or it may not have read and write permissions, and it happens that the available memory is a small probability event.
1 #include <iostream> 2 #include <cstdlib> 3 using namespace std; 4 5 class Complex{ 6 public: 7 Complex(double real = 0.0, double imag = 0.0): m_real(real), m_imag(imag){ } 8 public: 9 operator double() const { return m_real; } //类型转换函数 10 private: 11 double m_real; 12 double m_imag; 13 }; 14 15 int main(){ 16 // the following is the correct usage 17 int m = 100 ; 18 Complex c( 12.5 , 23.8 ); 19 long n = static_cast< long >(m); // Wide conversion, no information loss 20 char ch = static_cast< char >(m); // Narrow conversion, information may be lost 21 int *p1 = static_cast< int *>( malloc ( 10 * sizeof (int )) ); // Convert void pointer to concrete type pointer 22 void *p2 = static_cast< void *>(p1); // Convert concrete type pointer to void pointer 23 double real= static_cast< double >(c ); // call the type conversion function 24 25 // the following usage is wrong 26 float *p3 = static_cast< float *>(p1); // cannot convert between pointers of two concrete types 27 p3 = static_cast < float *>( 0X2DF9 ); // Cannot convert integer to pointer type 28 29 return 0 ; 30 }
const_cast keyword
Convert const type to non-const type
1 #include <iostream> 2 using namespace std; 3 4 int main(){ 5 const int n = 100; 6 int *p = const_cast<int*>(&n); 7 *p = 234; 8 cout<<"n = "<<n<<endl; 9 cout<<"*p = "<<*p<<endl; 10 11 return 0; 12 }
operation result:
n = 100;
*p = 234;
&n
Used to obtain the address of n, its type is const int *
, must be converted to type using const_cast int *
before assigning to p. Since p points to n, and n occupies stack memory and has write permission, the value of n can be modified through p.
Some readers may ask, why are the values output by n and *p different? This is because C++'s treatment of constants is more like compile-time #define
, a process of value substitution. All the places where n is used in the code are replaced by 100 during compile-time. In other words, line 8 has been modified to look like this:
cout<<"n = "<<100<<endl;
reinterpret_cast keyword
1 #include <iostream> 2 using namespace std; 3 4 class A{ 5 public: 6 A(int a = 0, int b = 0): m_a(a), m_b(b){} 7 private: 8 int m_a; 9 int m_b; 10 }; 11 12 int main(){ 13 //将 char* 转换为 float* 14 char str[]="http://c.biancheng.net"; 15 float *p1 = reinterpret_cast< float *> (str); 16 cout<<*p1<< endl; 17 // cast int to int* 18 int *p = reinterpret_cast< int *>( 100 ); 19 // Convert A* to int* 20 p = reinterpret_cast< int *>( new A( 25 , 96 )); 21 cout<<*p<< endl; 22 23 return 0 ; 24 }
dynamic_cast keyword
dynamic_ is used for type conversion in the inheritance hierarchy of the class, allowing upcasting and downcasting. There is no detection for up transition, and down transition needs to be checked by rtti, which is only partially successful.
Syntax format:
dynamic_cast<newType>(rxpression)
newType and expression must be both pointer types or reference types. In other words, dynamic_cast can only convert pointer types and reference types, other types (int,
double, arrays, classes, structs, etc.) will not work.