63.C++类型转换
类型转换(cast)是将一种数据类型转换成另一种数据类型。例如,如果将一个整型值赋给一个浮点类型的变量,编译器会暗地里将其转换成浮点类型。
转换是非常有用的,但是它也会带来一些问题,比如在转换指针时,我们很可能将其转换成一个比它更大的类型,但这可能会破坏其他的数据。
应该小心类型转换,因为转换也就相当于对编译器说:忘记类型检查,把它看做其他的类型。
一般情况下,尽量少的去使用类型转换,除非用来解决非常特殊的问题。
无论什么原因,任何一个程序如果使用很多类型转换都值得怀疑。
标准c++提供了一个显示的转换的语法,来替代旧的C风格的类型转换。
使用C风格的强制转换可以把想要的任何东西转换成我们需要的类型。那为什么还需要一个新的C++类型的强制转换呢?
新类型的强制转换可以提供更好的控制强制转换过程,允许控制各种不同种类的强制转换。C++风格的强制转换其他的好处是,它们能更清晰的表明它们要干什么。程序员只要扫一眼这样的代码,就能立即知道一个强制转换的目的。
//2023年3月10日19:52:46
#pragma warning(disable:4996)
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <string>
using namespace std;
//静态转换
//1.基础类型转换
void test01()
{
char a = 'a';
//char->double;
//static_cast<目标类型>(待转类型)
double d = static_cast<double>(a);
//double d1 = (double)a;
}
//2.有层次关系的类的指针或引用转换
class Father
{
};
class Son :public Father
{
};
class Other
{
};
void test02()
{
Father* f = NULL;
Son* s = NULL;
//向下转换,不安全
static_cast<Son*>(f);
//向上转换,安全
Father* f1 = static_cast<Father*>(s);
//没有继承关系的类之间的指针不能转换
//Other* o = static_cast<Other*>(s);
}
//引用转换
void test03()
{
Father f;
Son s;
Father& ref_f = f;
Son& ref_s = s;
//向上转换,安全
static_cast<Father&>(ref_s);
//向下转换,不安全
static_cast<Son&>(ref_f);
}
//动态转换
void test04()
{
//char a = 'a';
//dynamic_cast<double>(a);//基础数据类型不能使用动态转换
Father* f = NULL;
Son* s = NULL;
//向上,安全
Father* f1 = dynamic_cast<Father*>(s);
//向下,不安全,会检查
//Son* s1 = dynamic_cast<Son *>(f);
}
class Father2
{
public:
virtual void func() {};
};
class Son2 :public Father2
{
public:
virtual void func() {};
};
//发生多态时,向下转换,动态转换就可以
void test05()
{
Father2* f = new Son2;
dynamic_cast<Son2*>(f);
}
//常量转换
void test06()
{
const int* p = NULL;
//const-->不带const
int* newP = const_cast<int*>(p);
int* pp = NULL;
const int* newPP = const_cast<const int*>(pp);
}
//重新解释转换
void test07()
{
int a = 10;
int* p = reinterpret_cast<int*>(a);
Father* f = NULL;
Other* o = reinterpret_cast<Other*>(f);
}
int main()
{
test05();
system("pause");
return EXIT_SUCCESS;
}
1.静态转换(static_cast)
●用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
▷进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
▷进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
●用于基本数据类型之间的转换,如把int转换成char,把char转换成int。这种转换的安全性也要开发人员来保证。
class Animal{};
class Dog : public Animal{};
class Other{};
//基础数据类型转换
void test01(){
char a = 'a';
double b = static_cast<double>(a);
}
//继承关系指针互相转换
void test02(){
//继承关系指针转换
Animal* animal01 = NULL;
Dog* dog01 = NULL;
//子类指针转成父类指针,安全
Animal* animal02 = static_cast<Animal*>(dog01);
//父类指针转成子类指针,不安全
Dog* dog02 = static_cast<Dog*>(animal01);
}
//继承关系引用相互转换
void test03(){
Animal ani_ref;
Dog dog_ref;
//继承关系指针转换
Animal& animal01 = ani_ref;
Dog& dog01 = dog_ref;
//子类指针转成父类指针,安全
Animal& animal02 = static_cast<Animal&>(dog01);
//父类指针转成子类指针,不安全
Dog& dog02 = static_cast<Dog&>(animal01);
}
//无继承关系指针转换
void test04(){
Animal* animal01 = NULL;
Other* other01 = NULL;
//转换失败
//Animal* animal02 = static_cast<Animal*>(other01);
}
2.动态转换(dynamic_cast)
●dynamic_cast主要用于类层次间的上行转换和下行转换;
●在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;
●在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全;
class Animal {
public:
virtual void ShowName() = 0;
};
class Dog : public Animal{
virtual void ShowName(){
cout << "I am a dog!" << endl;
}
};
class Other {
public:
void PrintSomething(){
cout << "我是其他类!" << endl;
}
};
//普通类型转换
void test01(){
//不支持基础数据类型
int a = 10;
//double a = dynamic_cast<double>(a);
}
//继承关系指针
void test02(){
Animal* animal01 = NULL;
Dog* dog01 = new Dog;
//子类指针转换成父类指针 可以
Animal* animal02 = dynamic_cast<Animal*>(dog01);
animal02->ShowName();
//父类指针转换成子类指针 不可以
//Dog* dog02 = dynamic_cast<Dog*>(animal01);
}
//继承关系引用
void test03(){
Dog dog_ref;
Dog& dog01 = dog_ref;
//子类引用转换成父类引用 可以
Animal& animal02 = dynamic_cast<Animal&>(dog01);
animal02.ShowName();
}
//无继承关系指针转换
void test04(){
Animal* animal01 = NULL;
Other* other = NULL;
//不可以
//Animal* animal02 = dynamic_cast<Animal*>(other);
}
3.常量转换(const_cast)
该运算符用来修改类型的const属性。。
●常量指针被转化成非常量指针,并且仍然指向原来的对象;
●常量引用被转换成非常量引用,并且仍然指向原来的对象;
注意:不能直接对非指针和非引用的变量使用const_cast操作符去直接移除它的const。
//常量指针转换成非常量指针
void test01(){
const int* p = NULL;
int* np = const_cast<int*>(p);
int* pp = NULL;
const int* npp = const_cast<const int*>(pp);
const int a = 10; //不能对非指针或非引用进行转换
//int b = const_cast<int>(a); }
//常量引用转换成非常量引用
void test02(){
int num = 10;
int & refNum = num;
const int& refNum2 = const_cast<const int&>(refNum);
}
4.重新解释转换(reinterpret_cast)
这是最不安全的一种转换机制,最有可能出问题。
主要用于将一种数据类型从一种类型转换为另一种类型。它可以将一个指针转换成一个整数,也可以将一个整数转换成一个指针.
63.C++类型转换的更多相关文章
- 密码学笔记-一段base64wp
CTF--练习平台 例题: 一段Base64 flag格式:flag{xxxxxxxxxxxxx} 附件: base64.txt 1.base64解码:http://base64.xpcha.com/ ...
- c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast
c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast [版权声明]转载请注明出处 http://www.cnblogs.c ...
- system verilog中的类型转换(type casting)、位宽转换(size casting)和符号转换(sign casting)
类型转换 verilog中,任何类型的任何数值都用来给任何类型赋值.verilog使用赋值语句自动将一种类型的数值转换为另一种类型. 例如,当一个wire类型赋值给一个reg类型的变量时,wire类型 ...
- C++库研究笔记——操作符重载实现类型转换&这样做的意义
目标: 已知这个接口: std::vector<double> add_vec(double *d1, double *d2) { ..... return result; } 我们自定义 ...
- java注释 命名 数据类型 基本类型转换 位运算符 逻辑运算符 三目运算符
一.java注释 1.单行注释 //注释内容 2.多行注释 /*注释内容*/ 3.文档注释(可用javadoc工具生成api文档,不过我还没试过)/**文档注释*/,文档注释可以在使用的时候看见注释 ...
- 从字节码看java类型转换【 深入理解 (T[]) new Object[size] 】
我们都知道,java中对类型的检查是很严格的,所以我们平操作时,也往往很小心. 如题: (T[]) new Object[size],这种写法是一般我们是不会干的!但是有点经验的同学,还是会遇到这样写 ...
- Java基本数据类型总结、类型转换、常量的声明规范,final关键字的用法
1 Java 基本数据类型 变量就是申请内存来存储值.也就是说,当创建变量的时候,需要在内存中申请空间. 内存管理系统根据变量的类型为变量分配存储空间,分配的空间只能用来储存该类型数据. 因此,通过 ...
- Python基本语法_强制数据类型转换
目录 目录 前言 软件环境 Python数据类型的显式转换 显式转换的多种类型 Non-String转换为String str函数 repr str和repr的区别 eval Non-int转换为in ...
- 类型转换运算符、*运算符重载、->运算符重载、operator new 和 operator delete
一.类型转换运算符 必须是成员函数,不能是友元函数 没有参数 不能指定返回类型 函数原型:operator 类型名(); C++ Code 1 2 3 4 5 6 7 8 9 10 11 12 1 ...
- C++之强制类型转换
C++ Code 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 ...
随机推荐
- 如何保证RabbitMQ的消息按照顺序执行???
可以采用单线程的消费保证消息的顺序性.对消息进行编号,1,2,3,4--消费时按照编号的顺序去消费消息.这样就可以保证消息 按照一定顺序执行.
- Templates && Algorithms
-[]基础算法 -[]递推和递归 -[]排序算法 -[]高精度,压位 -[]分治 -[]二分 -[]三分 -[]搜索算法 -[]简单搜索 -[]哈希和状态保存 -[]双向bfs -[]启发式搜索和DS ...
- 关于JDK1.8 java HashMap的tableSizeFor的解析:一个数最近2的幂次数方法
简介 一个数的最近2的幂次数,是java hashmap初始化方法指定容量里面对容量进行处理采用的方法 1.位运算符号介绍 符号 描述 运算规则 & 与 两个位都为1时,结果才为1 | 或 两 ...
- docker登录mysql
一.查看mysql是否已启动 二.登录mysql 三.假如需要重启mysql 查看docker中运行的容器docker ps,再重新启动mysql,docker restart 9299415df7f ...
- HTTP-看这一篇就够了
HTTP和HTTPS有什么区别 1.传输过程中信息是否加密,HTTP是超文本传输协议,信息是明文传输,HTTPS是具有安全性的SSL加密的超文本传输协议,信息是加密传输: 2.服务端使用的端口号不一致 ...
- vue表格拖拽使用Sortable插件库
1 <template > 2 <el-table 3 row-key="name" 4 :data="tableData" 5 stripe ...
- Spring系列之验证-14
目录 Java Bean 验证 Bean 验证概述 配置 Bean 验证提供程序 注入验证器 配置一个`DataBinder` Spring MVC 3 验证 Java Bean 验证 Bean 验证 ...
- 329MD5的加密
一.引用帮助类 二.登录的代码
- mysql数据库如何支持emoji表情
mysql数据库的默认字符集utf8,只能存储3个字节的数据.标准的emoji表情是4个字节,在APP端输入 保存表情是用户的普遍需求和行为. 插入数据库报错如下: java.sql.SQLExcep ...
- git的基础指令练习
#版本回退 git reset commitId --hard