541-C + + provides four types of conversion methods

In C language, type coercion is generally like this:

int a = (int)b;//It is unsafe to forcibly convert the type on the right to the type on the left. According to the forcibly converted type, the memory size may expand and the access is unsafe

Four types of conversion methods provided at the C + + language level

const_cast : A type conversion that removes (pointer or reference) constant attributes
static_cast : Provide type conversion that the compiler considers safe (conversion between types without any connection is denied and compilation fails)
reinterpret_cast : be similar to C Style of cast, there is no security
dynamic_cast : It is mainly used in inheritance structure and can support RTTI Up-down conversion of type identification

const_cast

A type conversion that removes (pointer or reference) constant attributes

It can be regarded as a template.

The bottom assembly instructions as like as two peas.
But before the conversion into assembly instructions, the compilation phase is different.

There is no problem compiling.

But if so:

In C + +, the address of an integer constant is converted into a pointer of another type whose pointer type does not match.

The compiler reported an error.


const_ During type forced conversion of cast, the type of address a should be consistent with the type on the left and the type without constant in < >

So const_cast can promise
Strong conversion is at the language level and does not produce any additional instruction code. These two sentences have no difference in assembly instructions.

Let's give another example:


static_cast

Provide type conversion that the compiler considers safe (conversion between types without any connection is denied and compilation fails)

int and char are related, so the conversion is no problem.

however


There is no connection between these two pointers, so they are rejected.



If you are successful, the pointer b of double type points to an integer memory. When this b is dereferenced, it is 8 bytes of memory, but in fact there is only 4 bytes of integer memory, which is unsafe.


The underlying type of C is strong, regardless of whether there is a connection between your types


Because base class types and derived class types are top-down types in inheritance structure.
When types are strong, there is a relationship between their types.
static_cast can be converted between them, but after conversion, whether the code is safe or not is guaranteed by the developer, not by static_cast guarantee.


reinterpret_cast: similar to C-style forced type conversion, it can be converted at will without any security


The pointer dereferences 8 bytes, while the original memory is only 4 bytes, resulting in insecurity.

dynamic_cast

It is mainly used in inheritance structure and can support up-down conversion of RTTI type recognition





However, it is possible that with the progress of the project, the requirements for software development have changed, and we need to add new requirements:

class Base//abstract class 
{
public:
	virtual void func() = 0;
};
class Derive1 : public Base
{
public:
	void func() { cout << "call Derive1::func" << endl; }
};
class Derive2 : public Base
{
public:
	void func() { cout << "call Derive2::func" << endl; }
	//Derive2 API interface function for new functions
	void derive02func() 
	{ 
		cout << "call Derive2::derive02func" << endl; 
	}
};

Then, judge in the following function:
If you point to an object of another derived class, you can call this func. However, if you point to an object of Derive2, do not call this func method, but call the derive02fun method.

Our current software design is to realize this function. What can we do?
Now we need to identify the type of * p and which object it points to. If it is the Derive object, we need to call the function again
1. We can judge the type by comparing typeid(*p).name() == "Derive"
The p pointer is a pointer of Base type, which is a virtual function. It identifies the dynamic binding of runtime, that is, the object pointed to by the pointer, and then accesses its virtual function table, taking the type of RTTI.

2. But now we use dynamic_cast for RTTI type conversion

class Base//abstract class 
{
public:
	virtual void func() = 0;
};
class Derive1 : public Base
{
public:
	void func() { cout << "call Derive1::func" << endl; }
};
class Derive2 : public Base
{
public:
	void func() { cout << "call Derive2::func" << endl; }
	//Derive2 API interface function for new functions
	void derive02func() 
	{ 
		cout << "call Derive2::derive02func" << endl; 
	}
};
/*
typeid(*p).name() == "Derive"
*/
void showFunc(Base *p)
{
	//dynamic_cast will check whether the p pointer points to an object of type Derive2?
	//Access - > vftable RTTI information via p - > vfptr. If yes, dynamic_cast conversion type succeeded,
	//Return the address of the Derive2 object to pd2; Otherwise, nullptr is returned
	//static_cast is a compile time type conversion dynamic_cast is a runtime type conversion that supports RTTI information recognition
	Derive2 *pd2 = dynamic_cast<Derive2*>(p);
	if (pd2 != nullptr)
	{
		pd2->derive02func();
	}
	else
	{
		p->func();//Type derive2 derive02ffunc of dynamic binding * p
	}
}
int main()
{
	Derive1 d1;
	Derive2 d2;
	showFunc(&d1);
	showFunc(&d2);

	return 0;
}


Using static_cast can also be converted successfully because Base and Derive are associated and inherited, but they can always be converted successfully. Therefore, Derive2 cannot be recognized. It looks like Derive2 object, but it may actually be other derived class objects, which is very unsafe.

Tags: C++

Posted on Sat, 11 Sep 2021 01:56:27 -0400 by aravind_mg