【C++ 语言】类型转换 ( 转换操作符 | const_cast | static_cast | dynamic_cast | reinterpret_cast | 字符串转换 )

250 篇文章 187 订阅



I . const_cast 转换操作符


1. 类型转换方式 : ① C 语言中的强制类型转换 , ② 使用转换操作符进行转换 ;

2. const_cast 转换操作符 : 主要用来修改类型的 const 与 volatile 属性 ;

  • ① const 属性作用 : 修饰常量 ;
  • ② volatile 属性作用 : 保证获取一个变量值时 , 重新从内存读取该属性 ;

3. const 属性转换 : 使用 const_cast 转换 const 属性 , 就是将常量类型转为变量类型 , 或者将变量类型转为常量类型 ;

4. const_cast 转换操作符代码示例 :

  • ① 声明一个常量类型 : 声明一个字符串常量 ;
	const char* str_const = "Hello";
  • ② 将常量转为变量 : 格式为 " const_cast < 要转换的目标类型 > ( 常量或变量名称 ) " ;
	char* str = const_cast<char*> (str_const);
  • ③ 完整代码示例 :
	//新式转换 : 
	//转换操作符 : 
	//const_cast : 主要用来修改类型的 const 与 volatile 属性 , 
	//	将不可修改属性 const 转为 可修改的属性
	//	volatile 属性作用 : 保证获取一个变量值时 , 重新从内存读取该属性 ; 

	//将 const char* 类型变量 转为 char* 类型的变量 
	//	可以理解成将常量转为变量 , 这里也可以将变量转为常量
	const char* str_const = "Hello";
	char* str = const_cast<char*> (str_const);

此处将 const char* 类型变量 转为 char* 类型的变量 , 可以理解成将常量转为变量 , 这里也可以将变量转为常量 ;



II . static_cast 转换操作符


1. static_cast 转换操作符 : 有以下作用 ;

  • ① 基础类型转换 : int 与 float 之间进行转换 等 ;
  • ② 指针类型转换 : void* 与 指针类型之间转换 , 如 void* 与 int* 之间转换 ;
  • ③ 子类与父类之间转换 : 子类指针与父类指针之间的转换 , 子类引用与父类引用之间的转换 ;

2. 定义子类与父类 : 其中父类中定义两个函数 , 分别是普通函数和虚函数 , 子类重写这两个函数 ;

//定义父类 , 其中定义共有虚函数
//	虚函数主要是能根据实际类型调用对应方法
class Parent {
public:
	void function() {
		cout << " 父类方法 " << endl;
	}

	virtual void function_viurtual() {
		cout << " 父类虚函数 " << endl;
	}
};

//定义子类 , 共有继承父类 , 
//	将父类的方法和属性都转为 public 
class Child : public Parent {
public :
	void function() {
		cout << " 子类方法 " << endl;
	}

	void function_viurtual() {
		cout << " 子类虚函数 " << endl;
	}
};

子类重写的普通函数与虚函数区别 :

  • 普通函数 : 编译时确定调用子类的方法还是父类的方法 , 根据声明确定调用谁的方法 , 类型声明成子类 , 就调用子类的方法 , 类型声明成父类 , 就调用父类的方法 ;
  • 虚函数 : 运行时确定调用的是子类的方法还是父类的方法 , 运行时调用哪个类的构造方法 , 该对象就是什么类型的 , 其调用对应类型的虚函数或虚函数实现 ;

3. 创建父类指针变量 :

	Parent* parent = new Parent();

4. 将父类指针变量转为子类指针 :

	Child* child = static_cast<Child*>(parent);

5. 分别调用子类和父类的普通函数 : 该函数调用父类还是子类的在编译时确定 ;

  • ① " child->function() " 讨论 : 调用子类 Child 的 function 方法 , 这里的 function 方法时普通方法 , 其声明的是什么类型的变量 , 那么调用的就是哪个类的方法 , 该对象声明的是 Child 对象 , 那么调用的就是 子类的方法 ;

  • ② " parent->function() " 讨论 : 调用父类 Parent 的 function 方法 , 同理 , parent 对象声明为 Parent 类型 , 那么其调用的方法就是父类的方法 ;

  • ③ 代码示例 :

	Parent* parent = new Parent();
	Child* child = static_cast<Child*>(parent);

	//调用子类 Child 的 function 方法
	//	这里的 function 方法时普通方法 , 其声明的是什么类型的变量 , 
	//	那么调用的就是哪个类的方法 , 该对象声明的是 Child 对象 , 
	//	那么调用的就是 子类的方法
	child->function();

	//调用父类 Parent 的 function 方法
	//	同理 , parent 对象声明为 Parent 类型 , 
	//	那么其调用的方法就是父类的方法
	parent->function();
  • ④ 执行结果 :
 子类方法
 父类方法

6. 分别调用子类和父类的虚函数 : 虚函数方法调用子类还是父类的 , 是运行时决定的 , parent 对象使用 new Parent() 进行创建 , 那么无论何时 , 其虚函数都是调用父类的方法 ;

  • ① 代码示例 :
	Parent* parent = new Parent();
	Child* child = static_cast<Child*>(parent);
	
	//这里测试调用子类和父类虚函数方法 , 
	//	与上面的结果不同 , 虚函数方法调用子类还是父类的 , 是运行时决定的 , 
	//	parent 对象使用 new Parent() 进行创建 , 
	//	那么无论何时 , 其虚函数都是调用父类的方法 ; 
	//	即使将其类型转为 Child 类型 , 其实际运行时的类型还是 Parent 类型
	//	调用的虚函数方法始终是父类的方法 ; 
	parent->function_viurtual();
	child->function_viurtual();
  • ② 执行结果 :
 父类虚函数
 父类虚函数

即使将其类型转为 Child 类型 , 其实际运行时的类型还是 Parent 类型 , 调用的虚函数方法始终是父类的方法 ;



III . dynamic_cast 转换操作符


1. dynamic_cast 转换操作符简介 :

  • ① 转换对象 : 该转换只对多态的情况下有效 , 主要是将父类转为子类或子类转成父类 ;
  • ② 作用 : 将父类 指针类型 变量转为子类 指针类型 变量 , 将父类 引用类型 变量转为子类 引用类型 变量 ;
  • ③ 安全性 : 这个动态转换操作是安全的 , 在运行期间对类型转换操作进行安全检查 ;

安全检查内容 1 : 使用 dynamic_cast 转换操作符, 进行父类与子类强制转换时 , 父类必须有一个虚函数 , 否则代码编写的时候就会报错 ( 运行时 dynamic_cast 的操作数必须包含多态类型 ) ; 下图是删除父类的虚函数后 , IDE 开发环境提示出的错误 ;
在这里插入图片描述

2. 安全检查内容 2 : 类型不符合转换要求 ( 主要是将父类转为子类或子类转成父类 ) , 会转换失败 , 返回 null ;

  • ① 报错行为 : 在父类中定义虚函数 , 在编写代码时没有报错 , 但是在运行时报错 ( 引发了异常 : 读取访问权限冲突 ) ;
  • ② 转换失败 : 这是因为创建的 parent1 对象是 Parent 父类类型的 , 将 Parent 类型动态强转成 Child 类型 , 该操作会转换失败 , 其转换结果是 null ;
  • ② 调用空对象方法 : 此时 child1 指针变量为 null , 调用 null 变量的方法 , 就会抛出上述异常 ;
    在这里插入图片描述

3. dynamic_cast 转换操作符转换失败示例 :

  • ① 代码示例 :
	//定义父类对象 , 然后将父类对象强转为子类对象
	Parent* parent1 = new Parent();
	Child* child1 = dynamic_cast<Child*>(parent1);

	//根据转换结果打印不同的信息
	if (!child1) {
		//如果 child1 变量是 0 , 说明其转换结果为 null , !child1 结果大于 0 
		cout << " 父类 Parent 指针变量 转为 子类 Child 指针变量 转换失败 " << endl;
	}
	else {
		//转换结果不为 null
		child1->function_viurtual();
	}
  • ② 执行结果 :
 父类 Parent 指针变量 转为 子类 Child 指针变量 转换失败

4. 转换成功的情况 : 转换成功的前提是 , 子类可以转成父类 , 但是父类不能转换成子类 ; 开始时要创建子类对象 , 将其赋值给父类变量 , 之后还可以将该变量再次转为子类对象 , 反之则不可行 , 转换会失败 ;

  • ① 代码示例 :
	//定义子类对象 , 然后将父类对象强转为子类对象
	Parent* parent2 = new Child();
	Child* child2 = dynamic_cast<Child*>(parent2);

	//根据转换结果打印不同的信息
	if (!child2) {
		//如果 child1 变量是 0 , 说明其转换结果为 null , !child1 结果大于 0 
		cout << " 父类 Parent 指针变量 转为 子类 Child 指针变量 转换失败 " << endl;
	}
	else {
		//转换结果不为 null
		child2->function_viurtual();
	}
  • ② 执行结果 :
 子类虚函数


IV . reinterpret_cast 转换操作符


reinterpret_cast 转换操作符作用 : 对指针变量 , 引用变量进行原始的转换 , 即将地址值转成对应的类型 ;

  • ① 代码示例 :
	// 4. reinterpret_cast 转换操作符

	//作用 : 对指针变量 , 引用变量进行原始的转换 ; 

	char* hello = "Hello";

	//获取 hello 字符串地址 , 将其转为 int 类型
	int hello_address = reinterpret_cast<int> (&hello);

	//打印 hello 的地址 , 并以 16 进制形式打印出来
	cout << hex << &hello << endl;
	//打印 hello_address , 并以 16 进制形式打印出来
	cout << hex << hello_address << endl;
  • ② 执行结果 :
000000B6B62FE898
b62fe898


V . int 与 char* 转换


1. char* 转 int : 字符串变量转成整型变量 , 调用 C 函数 atoi(char*) 函数可以将字符串变量转成 int 类型变量 ;
2. char* 转 float : 字符串变量转成浮点型变量 , 调用 atof(char*) 函数可以将字符串变量转成 float 类型变量 ;

3. int 转 char* 变量 :

  • ① 使用 itoa 函数 : 可以将 int 类型变量转为字符串 ;
  • ② 使用 sprintf 函数 : 也可以将 int 类型变量转为字符串 ;

4. int 与 char* 转换代码示例 :

  • ① 代码示例 :
	// 5. char* 与 int 进行转换

	//将字符串转为 int 类型变量
	int int_var = atoi("88888");

	//将字符串转为浮点型变量
	float float_var = atof("88.88f");

	//打印转换结果 : 注意要输出 十进制数
	cout << "int_var : " << dec << int_var << " float_var :  " << float_var << endl;


	//int 类型 转为字符串
	char c[10];
	itoa(888, c, 10);

	//打印转换后的字符串
	cout << c << endl;

	char c1[10];
	sprintf(c1, "%d", 8888);

	//打印转换后的字符串
	cout << c1 << endl;
  • ② 执行结果 :
int_var : 88888 float_var :  88.88
888
8888


VI . 类型转换代码示例


1. 代码示例 :

  • ① 父类子类定义 :
//定义父类 , 其中定义共有虚函数
//	虚函数主要是能根据实际类型调用对应方法
class Parent {
public:
	void function() {
		cout << " 父类方法 " << endl;
	}

	virtual void function_viurtual() {
		cout << " 父类虚函数 " << endl;
	}
};

//定义子类 , 共有继承父类 , 
//	将父类的方法和属性都转为 public 
class Child : public Parent {
public:
	void function() {
		cout << " 子类方法 " << endl;
	}

	void function_viurtual() {
		cout << " 子类虚函数 " << endl;
	}
};
  • ② 函数调用 :
	// IX . 类型转换

	//新式转换 : 
	// 1. const_cast 转换操作符 :
	//const_cast : 主要用来修改类型的 const 与 volatile 属性 , 
	//	将不可修改属性 const 转为 可修改的属性
	//	volatile 属性作用 : 保证获取一个变量值时 , 重新从内存读取该属性 ; 

	//将 const char* 类型变量 转为 char* 类型的变量 
	//	可以理解成将常量转为变量 , 这里也可以将变量转为常量
	const char* str_const = "Hello";
	char* str = const_cast<char*> (str_const);


	// 2. static_cast 转换操作符 

	//定义父类对象 , 然后将父类对象强转为子类对象
	Parent* parent = new Parent();
	Child* child = static_cast<Child*>(parent);

	//调用子类 Child 的 function 方法
	//	这里的 function 方法时普通方法 , 其声明的是什么类型的变量 , 
	//	那么调用的就是哪个类的方法 , 该对象声明的是 Child 对象 , 
	//	那么调用的就是 子类的方法
	child->function();

	//调用父类 Parent 的 function 方法
	//	同理 , parent 对象声明为 Parent 类型 , 
	//	那么其调用的方法就是父类的方法
	parent->function();


	//这里测试调用子类和父类虚函数方法 , 
	//	与上面的结果不同 , 虚函数方法调用子类还是父类的 , 是运行时决定的 , 
	//	parent 对象使用 new Parent() 进行创建 , 
	//	那么无论何时 , 其虚函数都是调用父类的方法 ; 
	//	即使将其类型转为 Child 类型 , 其实际运行时的类型还是 Parent 类型
	//	调用的虚函数方法始终是父类的方法 ; 
	parent->function_viurtual();
	child->function_viurtual();


	// 3. dynamic_cast 转换操作符
	
	//定义父类对象 , 然后将父类对象强转为子类对象
	Parent* parent1 = new Parent();
	Child* child1 = dynamic_cast<Child*>(parent1);

	//根据转换结果打印不同的信息
	if (!child1) {
		//如果 child1 变量是 0 , 说明其转换结果为 null , !child1 结果大于 0 
		cout << " 父类 Parent 指针变量 转为 子类 Child 指针变量 转换失败 " << endl;
	}
	else {
		//转换结果不为 null
		child1->function_viurtual();
	}


	//定义子类对象 , 然后将父类对象强转为子类对象
	Parent* parent2 = new Child();
	Child* child2 = dynamic_cast<Child*>(parent2);

	//根据转换结果打印不同的信息
	if (!child2) {
		//如果 child1 变量是 0 , 说明其转换结果为 null , !child1 结果大于 0 
		cout << " 父类 Parent 指针变量 转为 子类 Child 指针变量 转换失败 " << endl;
	}
	else {
		//转换结果不为 null
		child2->function_viurtual();
	}


	// 4. reinterpret_cast 转换操作符

	//作用 : 对指针变量 , 引用变量进行原始的转换 ; 

	char* hello = "Hello";

	//获取 hello 字符串地址 , 将其转为 int 类型
	int hello_address = reinterpret_cast<int> (&hello);

	//打印 hello 的地址 , 并以 16 进制形式打印出来
	cout << hex << &hello << endl;
	//打印 hello_address , 并以 16 进制形式打印出来
	cout << hex << hello_address << endl;


	// 5. char* 与 int 进行转换

	//将字符串转为 int 类型变量
	int int_var = atoi("88888");

	//将字符串转为浮点型变量
	float float_var = atof("88.88f");

	//打印转换结果 : 注意要输出 十进制数
	cout << "int_var : " << dec << int_var << " float_var :  " << float_var << endl;


	//int 类型 转为字符串
	char c[10];
	itoa(888, c, 10);

	//打印转换后的字符串
	cout << c << endl;

	char c1[10];
	sprintf(c1, "%d", 8888);

	//打印转换后的字符串
	cout << c1 << endl;

2. 执行结果 :

 子类方法
 父类方法
 父类虚函数
 父类虚函数
 父类 Parent 指针变量 转为 子类 Child 指针变量 转换失败
 子类虚函数
00000033C8AFE698
c8afe698
int_var : 88888 float_var :  88.88
888
8888
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值