C++ type conversion summary

  • 2020-04-02 02:30:12
  • OfStack

Anyone who has studied C++ knows that C++ is a strongly typed language, so variables must declare data types before they are used, and different data types allocate different amounts of memory space. This is especially important when converting types to prevent data loss or overflows. This article will summarize the type conversion of C++ in detail.

C++ evolved from C and also inherited two c-style transformations: implicit and explicit.

1. Implicit conversion

Implicit conversion refers to the type conversion automatically carried out by the compilation system without manual intervention, for example:


short a = 2000;
int b;
b = a;

Implicit conversions also include conversions of constructors and operators, such as:


class A {};
class B {
public: 
  B (A a) {}
};

 
A a;
B b = a;

2. Explicit conversion

In contrast to implicit conversions, explicit conversions take advantage of the cast operator, for example:


double x = 10.3;
int y;
y = int (x);  //Let me write it as a function
y = (int) x;  //C style

The above conversions already satisfy the basic conversions. But if you want to convert classes and Pointers, sometimes the code compiles and makes errors while running. Such as:


#include <iostream>

class CDummy {
  float i,j;
public:
  CDummy () { i=1; j=1; }
};

class CAddition {
  int x,y;
public:
  CAddition () { x=1; y=1; }
  int result() { return x+y;}
};

int main () {
 CDummy d;
 CAddition * padd;
 padd = (CAddition*) &d;
 std::cout << padd->result();
 return 0;
}

This code will make an error at run time when executing padd- > An exception occurs when result(), and some compilers exit with an exception.
Traditional unambiguous type conversions can be cast to any other pointer type any pointer, regardless of the type they point to. The result of a subsequent call to the member produces a run-time error or unexpected result.

C++ standard conversion operator

The traditional way of casting classes and Pointers is unsafe and can exit at run time. Standard C++ provides four conversion operators: dynamic_cast, reinterpret_cast, static_cast, and const_cast
dynamic_cast < new_type > (expression)
reinterpret_cast < new_type > (expression)
static_cast < new_type > (expression)
const_cast < new_type > (expression)

1. The dynamic_cast

Dynamic_cast can only be used for objects that are Pointers and references. The goal is to ensure that the result of the cast is a valid object that completes the requested class, so when we transition from a class to its parent, dynamic_cast always succeeds. Dynamic_cast can convert a NULL pointer to an unrelated class, or a void pointer to any type.


class CBase { };
class CDerived: public CBase { };
CBase b;
CDerived d;

CBase* pb = dynamic_cast<CBase*>(&d);    //Subclass to parent, correct
//CDerived* pd = dynamic_cast<CDerived*>(&b); //  Parent subclass, error 

When the new type is not the parent of the converted type, dynamic_cast cannot complete the conversion of the pointer and returns NULL. When dynamic_cast transforms a reference type, a Bad_cast exception is thrown when a failure is encountered.

2. Static_cast

Static_cast can perform conversions between Pointers to related classes, and between subclasses and superclasses, but it is not safe to convert a superclass pointer to a subclass pointer. The static_cast did not perform a security check at run time, so let's make sure the transformation is safe first. On the other hand, static_cast has less overhead in type safety checking than dynamic_cast.


class CBase {};
class CDerived: public CBase {};
CBase * a = new CBase;
CDerived * b = static_cast<CDerived*>(a);

The above code is legal, and b points to an incomplete object that may cause an error at run time.
Static_cast can also be used to perform any other non-pointer conversions, such as standard conversions between primitive types enum, struct, int, char, float, etc. :


double d = 3.14159265;
int i = static_cast<int>(d); 
void* p = static_cast<void*>(&i); //Any type is cast to type void

3. The reinterpret_cast

Reinterpret_cast converts to any other pointer type, even an unrelated class, any pointer type. The result of the operation is a reinterpretation of the type, but no binary conversion. All pointer conversions are allowed: either the content the pointer points to or the type of the pointer itself.


class A {};
class B {};
A * a = new A;
B * b = reinterpret_cast<B*>(a)

Reinterpret_cast can also be used to convert function pointer types, for example:


typedef void(*Func)();         //Declare a function pointer definition that returns void
Func pFunc;              //Define an array of type FuncPtr

//pFunc = &test;             //  Compilation error! Type mismatch 
pFunc = reinterpret_cast<Func>(&test); //Compile successfully! Convert function pointer type

4. Const_cast

Const_cast is used to manipulate the constants of objects, removing the const or volatile properties of types.


#include <iostream>

void print (char * str){
 std::cout << str ;
}

int main () {
 const char* c = "hello world";
 print ( const_cast<char *> (c) );
 return 0;
}

Related articles: