当前位置: 首页 > article >正文

C++:类型转换

目录

一、C语言中的类型转换

二、C++四种强制类型转换

static_cast

reinterpret_cast

const_cast

dynamic_cast



C++查找手册icon-default.png?t=N7T8https://legacy.cplusplus.com/

一、C语言中的类型转换

        模糊的讲,所有的类型转换都有一个不成文的约束:只有彼此有一定关联的类型才可以互相转换。

        C语言中的类型转换分为:

  • 隐式类型转换
  • 强制类型转换(显式类型转换)

        发生隐式类型转换的情况:

1.整型家族之间(int、short、char)
int i = 10;
char c = i;//编译通过,隐式类型转换
2.整型和浮点数之间
int i = 10;
double d = i;//编译通过、隐式类型转换
3.bool类型和整型
if(0)
while(1)
4.bool类型和指针
while(ptr)

        需要强制类型转换的情况

1.指针和整型
int i = 10;
int* p = &i;

int a = (int)p;//如果不强制类型转换,编译会报错
2.不同类型的指针之间
int i = 10;
int* p = &i;

char c = 'a';
char* pc = &c;

p = (int*)pc;//如果不强制类型转换,编译会报错

        而C++使用面向对象的思想,C++中的类型分为内置类型自定义类型,内置类型的互相转换规则同C语言一样,因此,C++的类型转换更多的讨论是关于内置类型自定义类型之间。

        自定义类型和内置类型之间的转换是通过构造函数支持的。

1.内置类型转换为自定义类型,由相应的构造函数实现,属于隐式类型转换
string s = "abcd";//本质是string支持const char* 的构造函数

const string& ss = "abcd";//引用要使用const,因为类型转换中间都会产生具有常性的临时变量
2.自定义类型转换为自定义类型,也是由构造函数支持
3.自定义类型转换为内置类型,需要特殊的重载函数,比如自定义类型A要转换为int
class A
{
public:
	operator int()
	{
		return _a1 + _a2;
	}
private:
	int _a1 = 1;
	int _a2 = 2;
};

        以上的类型转换规则,由于继承C的风格,有一些缺陷:转换的可视性差难以跟踪错误的转换。

        因此C++在保证兼容C风格的类型转换前提下,引入了四种命名形式的类型转换操作符

二、C++四种强制类型转换

static_cast

        static_cast用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可以用static_cast,但它不能用于两个不相关的类型进行转换。

int main()
{
	double d = 12.34;
	int a = static_cast<int>(d);
	cout << a << endl;
	return 0;
}

reinterpret_cast

        reinterpret_cast用来规范原来的强制类型转换。

int main()
{
	double d = 12.34;
	int a = static_cast<int>(d);
	cout << a << endl;
	// 这里使用static_cast会报错,应该使用reinterpret_cast
	//将int转换为指针
	int* p = reinterpret_cast<int*>(a);
	return 0;
}

const_cast

        const_cast一般用来去掉变量的const属性。

void Test()
{
	const int a = 2;
	int* p = const_cast<int*>(&a);//注意<>的类型一般为指针或引用
	*p = 3;
	cout << a << endl;
}

        运行结果

        可见我们的要求并没有实现(不是)。其实在内存中变量a的值已经修改为了3,但是由于寄存器中还存储着原来的值(因为是常量,并不会轻易修改),所以去掉const属性是会造成内存可视优化风险的,因此新增关键字volatile来解决。

void Test()
{
	volatile const int a = 2;
	int* p = const_cast<int*>(&a);
	*p = 3;
	cout << a << endl;
}


dynamic_cast

        dynamic_cast,在继承体系中,一般用于将父类对象的指针或引用动态的转换子类对象的指针或引用(向下转换)。

        在继承体系中,有两种转换的说法。

  • 向上类型转换

        向上转换是指子类对象“转换”为父类对象,本质不是类型转换,而是赋值兼容规则。

class A
{
public:
	int _a = 0;
    virtual void f() {}//该继承体系须支持多态
};

class B : public A
{
public:
	int _b = 1;
};

int main()
{
	//向上类型转换,其实不是类型转换,而是赋值兼容规则,子类向上“转换”为父类
	B bb;
	A aa = bb;
	A* ptr = &bb;
	return 0;
}
  • 向下转换

        向下转换是指父类对象“转换”为子类对象

void fun(A* pa);//A是父类

        根据继承中的语法规则

        如果pa原来指向子类,此时向下转换是安全的。

        如果pa原来指向父类,此时向下转换为子类,会造成越界访问,是不安全的。

        而dynamic_cast就是用来动态转换父子类。

void fun(A* pa)
{
	// 向下转换:父->子
	// pa指向子类对象,转回子类,是安全的
	// pa指向父类对象,转回子类,是不安全的,存在越界的风险问题

	// 传统写法,不安全
	//B* pb = (B*)pa;

	//  pa指向子类对象,转回子类,正常转换
	//  pa指向父类对象,转回子类,转换失败
	B* pb = dynamic_cast<B*>(pa);
	if (pb)
	{
		cout << pb << endl;
		cout << pb->_a << endl;
		cout << pb->_b << endl;
	}
	else
	{
		cout << "转换失败" << endl;
	}
}

RTTI(Run-time Type identification)运行时类型识别

        C++通过以下方式实现RTTI:

  • typeid运算符
  • dynamic_cast运算符
  • decltype 

http://www.kler.cn/news/292515.html

相关文章:

  • 12、Flink 解决流上的确定性最佳实践
  • 使用视图方式操作MySQL数据表
  • Java笔试面试题AI答之JDBC(1)
  • C语言-数据结构 无向图普里姆Prim算法(邻接矩阵存储)
  • selenium连接远程chrome浏览器
  • MIT线性代数
  • 【java】将Map的value类型定义为Object
  • 第十五题:三数之和
  • rancher搭建k8s及jenkins自动化部署
  • 骨传导耳机哪款好?精选五款热门骨传导耳机分享让你避免踩雷
  • 对HashMap的理解
  • 使用本地预训练模型可视化卷积每一部分
  • 基于自适应多变量超扭转的 Lyapunov 重新设计 RLV 姿态控制
  • Facebook与区块链:构建更安全的社交网络生态
  • MFC dll无法显示tooltip问题
  • Java-数据结构-链表-习题(三)(๑´ㅂ`๑)
  • java开发简历详解
  • Dubbo缓存
  • HTML 基础知识详解与代码示例
  • C++笔记16•数据结构:关联式容器map和set•
  • Java健康养老智慧相伴养老护理小程序系统源码代办陪诊陪护更安心
  • 阿里云身份证二要素详细使用
  • 第T2周:彩色图片分类
  • 828华为云征文|基于华为云Flexus云服务器X搭建jumpserver堡垒机软件
  • 电子病历、开药发药、住院检查、会员管理,SaaS模式B/S架构的云医院管理系统源码,云计算技术的医疗信息化解决方案
  • 经验笔记:Feeds流设计与实现
  • SpringMVC 第一次复学笔记
  • 解决 EasyExcel BigDecimal 加%的问题
  • 请解释Java Web中的Filter的作用和使用场景。什么是Java Web中的JSP?请解释其与Servlet的关系及各自优势。
  • OPC DA