4 types of type conversion operators in c++ (static_cast, reinterpret_cast, dynamic_cast, const_cast), volatile, RTTI

Table of Contents

introduce

introduce

static_cast

introduce

use

reinterpret_cast

introduce

use

const_cast

introduce

volatile

introduce

use

dynamic_cast

introduce

use

RTTI (runtime determination of type)

introduce

typeid operator

dynamic_cast operator

type_info class


Introduction

  • Originally in C, we have already been exposed to a lot of type conversions – implicit type conversions and explicit type conversions
  • Implicit — may result in loss of precision/ambiguous code/different compilers may handle implicit type conversions differently, and may also cause some pitfalls:
  • When pos=0, end will be promoted to size_t type in while, causing end=0 to still enter the loop, then -1, and finally lead to an infinite loop.
  • Explicit — There is only one format, (type) object being converted, which is not clear enough to view
  • Therefore, in order to enhance the visibility of type conversion and avoid some pitfalls, C++ has introduced 4 named cast operators, each with its own purpose.

Introduction

static_cast

Introduction

  • Used to perform the most common type conversions, such as conversion between numeric types and conversion of base class pointers to derived class pointers (that is, conversion between similar types conversion)
  • It is a relatively safe type conversion, but the programmer needs to ensure the safety of the conversion.

use

class A
{
public:
virtual void f() {}
};
class B : public A
{};

void test1() {
int a = 0;
double b = static_cast<double>(a);

A* pa = new B;
B* pb = static_cast<B*>(pa);
}
  • Although it is outrageous, static can indeed complete the conversion of base class pointers/references to derived classes.
  • But it is actually unsafe. It originally points to the base class object, but it is forced to point to the derived class. Then accessing [space beyond the original part] is still illegal

Conversion between dissimilar types like this is not allowed.

reinterpret_cast

Introduction

  • Can be used to convert dissimilar types
  • Has a very low level nature, it does not perform any type checking or safety checks

Use

What’s outrageous is that it can’t convert similar types:

const_cast

Introduction

The const type can easily be forced into a normal type in the C language. However, under vs2019/some compilers, compile-time optimization will be performed, const type variables will be replaced with constant values

You will find that tmp is a variable converted to int, + + is 43. In theory, a will be indirectly modified to 43, but it is not:

After checking the assembly, you will find that the value of a is directly pushed onto the stack using (2A=42)

And when we use the keyword “volatile“, we can let the compiler fetch the value of a from the memory instead of directly pushing the constant value.

volatile

Used to tell the compiler not to optimize variables marked volatile to ensure that the read and write operations of these variables will not be optimized out by the compiler, thus maintaining their original behavior.

Introduction

  • A conversion operator specifically used to remove the const attribute of [pointer/reference to a const object]
  • The converted type must also be a pointer/reference

Use

void modifyValue(int & amp; value) {
value = 100;
}

class MyClass {
public:
void nonConstFunction() {}
};

void test3() {
const int a = 42;
int & amp; aa = const_cast<int & amp;>(a);

const int b = 42;
modifyValue(const_cast<int & amp;>(b)); //The value of b can be modified (note that it must be a function passed in by reference)
cout << b << endl;

const MyClass obj;
const_cast<MyClass &>(obj).nonConstFunction();//You can call ordinary member functions
}

dynamic_cast

Introduction

  • Mainly used for safe downward transformation in inheritance relationships (that is, parent to child)
  • Provides the ability to check and perform type conversions at runtime to ensure the safety of conversions

Use

  • The parent class must have a virtual function
  • It must be ensured that thisparent class pointer/reference actually points to the subclass object (that is, let it restore its previous pointing)
  • If the conversion fails, return 0
  • class A
    {
    public:
    virtual void f() {}
    };
    class B : public A
    {};
    
    void func(A* pa)
    {
    // dynamic_cast will first check whether the conversion can be successful. If it can be converted successfully, it will be converted. If not, it will be returned.
    B* pb1 = static_cast<B*>(pa);
    B* pb2 = dynamic_cast<B*>(pa);
    cout << "pb1:" << pb1 << endl;
    cout << "pb2:" << pb2 << endl;
    }
    void test4() {
    A a;
    B b;
    func(&a);
    func(& amp;b);
    }
  • When a pointer to the parent class is passed in here, static_cast can complete the conversion to the subclass, but dynamic_cast cannot
  • And if it is a parent class pointer that originally points to a subclass, dynamic_cast will do.

RTTI(Runtime Determined Type)

Introduction

RTTI allows the program to determine the actual type of an object at runtime, which is useful when dealing with polymorphic inheritance relationships and base class pointers/references.

RTTI is mainly implemented through the following two operators and a class:

typeid operator

  • Used to obtain the type information of an object, it returns a type_info object that contains information about the type
  • Mainly used to check the type of objects and perform type comparisons

dynamic_cast operator

It checks the actual type of the object and performs type conversion based on the type information

type_info class

Obtained through typeid, used to store type information