C语言中经常会遇到类型的强转,强制类型转换是有一定风险的,有的转换并不一定安全,如把整型数值转换成指针,把基类指针转换成派生类指针,把一种函数指针转换成另一种函数指针,把常量指针转换成非常量指针等。

1.C语言中强转的方法及问题

1.1 C语言中的强转方法

    int n = 1;
	
	//将n的地址赋给指针p
	//int* p = &n;

	//c语言中进行强制转换,将n作为一个地址赋给p
	//p是带有类型的地址
	int* p = (int*)n;

当对地址为1的p进行访问的时候,会报如下错误:

int main()
{
	int n = 1;
	
	//c语言中进行强制转换,将n作为一个地址赋给p
	//p是带有类型的地址
	int* p = (int*)n;

	//代表在地址为1的地方赋值为1
	*p = 1;

	return 0;
}

在这里插入图片描述
基类转换为派生类的问题:由于派生类可能成员更多,基类转换为派生类可能越界访问。
函数指针的问题:由于函数的参数存在差异

1.2 C语言强制类型转换缺点

主要是为了克服C语言强制类型转换的以下三个缺点。

  • 没有从形式上体现转换功能和风险的不同。

    例如,将 int 强制转换成 double 是没有风险的,而将常量指针转换成非常量指针,将基类指针转换成派生类指针都是高风险的,而且后两者带来的风险不同(即可能引发不同种类的错误),C语言的强制类型转换形式对这些不同并不加以区分。

  • 将多态基类指针转换成派生类指针时不检查安全性,即无法判断转换后的指针是否确实指向一个派生类对象。

  • 难以在程序中寻找到底什么地方进行了强制类型转换。

    强制类型转换是引发程序运行时错误的一个原因,因此在程序出错时,可能就会想到是不是有哪些强制类型转换出了问题。

2. 强制转换运算符

C++ 引入了四种功能不同的强制类型转换运算符以进行强制类型转换:

  • const_cast

  • static_cast

  • reinterpret_cast 较少使用

  • dynamic_cast 虚函数中用的比较多

利用C++提供的运算符,就可以从编译器的角度上,最大的去支持检测安全性,鲁棒性更强。

3.const_cast

仅用于进行去除 const 属性的转换,它也是四个强制类型转换运算符中唯一能够去除 const 属性的运算符。

3.1 常用方法:利用const_cast 转换为同类型的非 const 引用或者指针

  • <>内为转换的目标,()内为要转换的值
  • const_cast只针对指针、引用、this指针

#include <iostream>
#include <string>

int main() {
	const int n = 5;
	const std::string s = "Inception";

	//<>内为转换的目标,()内为要转换的值
	//const_cast只针对指针、引用、this指针
	int* k=const_cast<int*>(&n);//指针
	*k = 123;

	int& kRef = const_cast<int&>(n);//引用
	kRef = 456;

}

下面为利用const_cast进行强制转换,利用指针和引用改变n的值的方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2 常成员函数中去除this指针的const属性

3.2.1 常成员函数不能修改成员变量的值

//常成员函数,不能修改成员变量的值
void foo(int nTest) const {}

运行结果如下:
在这里插入图片描述

3.2.2 为什么常成员函数不能修改成员变量的原因

先复习一下,之前学过的const的使用:

const int* p;//代表指针指向的内容是不变的
int =5;
int* const p=&n;//代表p本身的值(地址)不可以该表
class CTest
{
public:
	CTest() : m_nTest(2) {}
	//常成员函数,不能修改成员变量的值
	void foo(int nTest) const {
		void* p = this;
		//m_nTest = nTest;

		//m_nTest = nTest; 错误
		//const_cast<CTest*>(this)->m_nTest = nTest;
	}

public:
	int m_nTest;
};

int main() {
	CTest t;
	t.foo(1);
}

运行结果如下:
const在类的前面,代表指针指向的内容是不变的,也就是类的成员变量是不可以改变的。
在这里插入图片描述

3.2.3 可以通过const_cast去除类前面的const属性

//<CTest* const>指针地址不可改变,(this)代表常成员函数的this指针
//const_cast去除CTest*前面的const
const_cast<CTest* const>(this)->m_nTest = nTest;

#include <iostream>
#include <string>

class CTest
{
public:
	CTest() : m_nTest(2) {}
	//常成员函数,不能修改成员变量的值
	void foo(int nTest) const {
		//void* p = this;
		//m_nTest = nTest;

		//m_nTest = nTest; 错误

		//<CTest* const>指针地址不可改变,(this)代表常成员函数的this指针
		//const_cast去除CTest*前面的const
		const_cast<CTest* const>(this)->m_nTest = nTest;
	}

public:
	int m_nTest;
};

int main() {
	CTest t;
	t.foo(1);
}

4.学习视频地址:强制转换const_cast
5.学习笔记:强制转换const_cast笔记

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐