目录

1. C的类型转换

1. 显式类型转换

2. 隐式类型转换

3. 总结

2. C++强制类型转换

2.1. static_cast

2.2. reinterpret_cast

2.3. const_cast

2.4. dynamic_cast

3. 为什么需要强制类型转换

4. RTTI


1. C的类型转换

1. 显式类型转换

void Test1(void)
{
	// 显式类型转换
	int* ptr = nullptr;
	//int i = ptr;   // 默认情况下,指针不支持隐式类型转换为整形
	int i = (int)ptr; //  但是可以支持强转
}

2. 隐式类型转换

void Test2(void)
{
	double d = 1.1;
	int i = d;   //意义相近的类型,支持隐式类型转换
}

3. 总结

2. C++强制类型转换

2.1. static_cast

void Test3()
{
	// 静态类型转换 static_cast
	// 支持合理的转换
	double d = 1.1;
	int i = static_cast<int>(d);   
	// 不支持合理的转换,例如将指针转换为整形
	int* ptr = nullptr;
	int i = static_cast<int>(ptr);  // 编译报错
}

2.2. reinterpret_cast

void Test4(void)
{
	// 重新解释类型转换 reinterpret_cast
	// 可以将一个指针转化为一个整形
	int* ptr = nullptr;
	int i = reinterpret_cast<int>(ptr);
	std::cout << ptr << std::endl;
	// 也可以将一个整形转化为指针
	int j = 5;
	int* ptr1 = reinterpret_cast<int*>(i);
}

2.3. const_cast

void Test5(void)
{
	const int i = 5;
    // int*     -----   const int*
	int*p = const_cast<int*>(&i);
	*p = 10;

	std::cout << i << std::endl;
	std::cout << *p << std::endl;
}

C++的类型转换-LMLPHP

C++的类型转换-LMLPHP

C++的类型转换-LMLPHP 

void Test5(void)
{
	volatile const int i = 5;
	int*p = const_cast<int*>(&i);
	*p = 10;

	std::cout << i << std::endl;
	std::cout << *p << std::endl;
}

C++的类型转换-LMLPHP  

顺便,在这里提醒一下,上面都是C++规范的操作,有时候,它也可以这样:

void Test5(void)
{
	volatile const int i = 5;
	//int*p = const_cast<int*>(&i);  // C++规范做法
	int* p = (int*)&i;  // C++兼容C的做法,当然结果一致
	*p = 10;
	std::cout << i << std::endl;
	std::cout << *p << std::endl;
}

2.4. dynamic_cast

class base
{
public:
	int _a = 5;
};

class derive : public base
{
public:
	int _b = 10;
};

C++的类型转换-LMLPHP 

void Test6(void)
{
    derive d_target;
    // C++ 支持派生类向上"转型"为基类
	base b_target = d_target;   // 派生类对象切片为基类对象
    // 如果这是类型转换,这里都编不过,因此这些都不是类型转换
	base* p_target = &d_target;  // 派生类指针切片为基类指针
	base& r_target = d_target;  // 派生类引用切片为基类引用

    // 例如:
    double d = 1.1;
    //C++兼容C的不规范的转换
    int& i = d;   // 这里编译报错,为什么?
    // C++规范的转换
    int& i = static_cast<int>(d);  // 但同样会报错
    // 因为这里是类型转换,而类型转换都会生成一个临时变量,临时变量是右值
    // 因此我们这里需要加const,引用右值
    const int& i = static_cast<int>(d);
}
void Test6(void)
{
	base b_target;
	derive d_target;
	derive new_target = reinterpret_cast<derive>(b_target);  //编译报错
	//derive new_target = (derive)(b_target);
}
void func(base* ptr)
{
    // 这里是支持的,可以将父类指针强转为子类指针
	derive* dp = reinterpret_cast<derive*>(ptr); 
    std::cout << dp->_a << " : " << dp->_b << std::endl;
	dp->_a = 5;
	dp->_b = 10;
}

void Test7(void)
{
	base b;
	derive d;
	func(&b);
	func(&d);
}

C++的类型转换-LMLPHP

C++的类型转换-LMLPHP

class base
{
public:
	virtual void func(void){}
public:
	int _a = 5;
};

class derive : public base
{
public:
	int _b = 10;
};
void func(base* ptr)
{
	derive* dp = dynamic_cast<derive*>(ptr);
	// 如果ptr指向子类对象,转换成功
	if (dp != nullptr)
	{
		std::cout << dp->_a << " : " << dp->_b << std::endl;
		dp->_a = 10;
		dp->_b = 20;
	}
	// 如果ptr指向父类对象,转换失败,并返回空
	else
	{
		std::cout << dp << std::endl;
	}
}

void func(base& ptr)
{
	// 如果ptr指向子类对象,转换成功
	// 如果ptr指向父类对象,抛异常,具体为:std::bad_cast异常
	derive dp = dynamic_cast<derive&>(ptr);
	std::cout << dp._a << " : " << dp._b << std::endl;
	dp._a = 10;
	dp._b = 20;
}

 扩展问题:

namespace tmp
{
	class base1
	{
	public:
		virtual void func(void){}
	public:
		int _a1 = 5;
	};
	class base2
	{
	public:
		virtual void func(void){}
	public:
		int _a2 = 10;
	};
	class derive : public base1, public base2
	{
	public:
		int _b = 20;
	};
}

C++的类型转换-LMLPHP 

void Test8(void)
{
	tmp::derive d_target;
	tmp::base1* bp1 = &d_target;
	tmp::base2* bp2 = &d_target;
    std::cout << bp1 << std::endl;
	std::cout << bp2 << std::endl;
	std::cout << "------------------" << std::endl;
    // C++兼容C语言的类型强转
	tmp::derive* dp1 = (tmp::derive*)bp1;
	tmp::derive* dp2 = (tmp::derive*)bp2;
	std::cout << dp1 << std::endl;
	std::cout << dp2 << std::endl;
    std::cout << "------------------" << std::endl;
    // C++规范的类型强转
	tmp::derive* dp3 = reinterpret_cast<tmp::derive*>(bp1);
	tmp::derive* dp4 = reinterpret_cast<tmp::derive*>(bp2);
	std::cout << dp3 << std::endl;
	std::cout << dp4 << std::endl;
    std::cout << "------------------" << std::endl;
    // C++的动态转换
    // 要求基类必须是多态类型
	tmp::derive* dp5 = dynamic_cast<tmp::derive*>(bp1);
	tmp::derive* dp6 = dynamic_cast<tmp::derive*>(bp2);
	std::cout << dp5 << std::endl;
	std::cout << dp6 << std::endl;
    std::cout << "------------------" << std::endl;
}

 

3. 为什么需要强制类型转换

4. RTTI

int i = 10;
//推导一个对象的类型,其结果可以定义一个新的对象
decltype(i) j = 0;
10-22 16:59