【C++学习笔记】----C++类型转换(static_cast、reinterpret_cast、const_cast、dynamic_cast)

1.C语言类型转换
  • 主要代码
void test_c()
{
	//隐式类型转换
	int i = 1;
	double d = i;
	printf("i = %d ,d = %.2f\n", i, d);

	//显式类型转换
	int *p = &i;
	int address =(int)p;
	printf("p = %p , address = %d\n", p, address);
}
  • 隐式类型转换可能会出现精度丢失的情况,是有编译器完成
  • 显式类型转换是强转得到,代码不够清晰
2.C++类型转换
  1. static_cast
  • 核心代码
//相近类型(隐式类型)
void test_static_cast()
{
	//转换失败
	A a;
	int pa = static_cast<int>(a);
	
	double d = 10.5;
	int i = static_cast<int>(d);
	cout << i << endl;
}

  • 区分隐式类型转换,不能用于不相关的类型转换
  1. reinterpret_cast
  • 核心代码
//不相近类型(强转)
void test_reinterpret_cast()
{
	int *p = nullptr;
	int i = 10;
	p = (int*)i;
	cout << p << endl;
	p = reinterpret_cast<int*>(i);
	cout << p << endl;
}
  • 用于不相关类型转换
  1. const_cast
  • 核心代码
void test_const_cast()
{
	//const_cast
	int i1 = 10;
	int *p1 = const_cast<int*>(&i1);
	*p1 = 5;
	cout << "i1->" << i1 << " " << "*p1->" << *p1 << endl;
	//有const 的原来的值不变,因为const的值在寄存器(由于编译器优化)里面,而改掉的值是在内存里的
	const int i2 = 10;
	int *p2 = const_cast<int*>(&i2);
	*p2 = 5;
	cout << "i2->" << i2 << " " << "*p2->" << *p2 << endl;
	//volatile防止编译器优化
	volatile const int i3 = 10;
	int *p3 = const_cast<int*>(&i3);
	*p3 = 5;
	cout << "i3->" << i3 << " " << "*p3->" << *p3 << endl;
}
  • 仅仅是去除const属性,需要注意的是,原来有const的数据,由于编译器优化,它在寄存器里,所以即便是更改了,原来的数据还是不会变,因为我们改掉的数据是内存里面的,如果要改掉原来的数据,那么我们可以去掉编译器优化,通过volatile。
  • 结果展示
    结果展示
  1. dynamic_cast
  • 核心代码
void fun(A* p)
{
	/*A* pa = p;
	pa->_a;
	//强转越界访问了
	B* pb = (B*)p;
	pb->_b;*/

	
	B* b = dynamic_cast<B*>(p);
	if (b)
		cout << "指向子类,转换成功" << endl;
	else
		cout << "指向父类,转换失败" << endl;
	
}
//多态类型的转换,(父类对象必须包换虚函数)
//dynamic_cast是到指针指向对象的虚表上方找到对象的标识信息
void test_dynamic_cast() 
{
	//子类对象给父类,切片
	A a;
	B b;

	A* pa = &a;
	fun(pa);

	pa = &b;
	fun(pa);

}
  • dynamic_cast是为了向下转换,转换是安全的,将父类转化为子类的引用或者指针(动态转化)

  • 只能用于含有虚函数的类,通过虚函数表找到标识信息。

  • 结果展示

  • 向上兼容的话是子类转化为父类,赋值兼容规则就可以,切片。

3.explicit防止构造隐式类型转化
  • 核心代码
void  test_explicit()
{
	C c1(1);
	C c2(c1);

	//隐式类型转换,没写 = ,但是会隐式类型转换成 C tmp(1)-> C c3(tmp)从而构造出来c3
	//C c3 = 1;
	
}
  • =会隐式类型转化出临时对象,然后拷贝构造完成,对象的构造,采用explicit防止转化
  • 多个参数可以通过参数列表完成对象构造{1,2}.
4.代码展示
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;

//C语言类型转换
void test_c()
{
	//隐式类型转换
	int i = 1;
	double d = i;
	printf("i = %d ,d = %.2f\n", i, d);

	//显式类型转换
	int *p = &i;
	int address =(int)p;
	printf("p = %p , address = %d\n", p, address);
}
//C++ 4种类型转换

class A
{
public:
	virtual void f() {}
	int _a=1;
};
class B:public A	
{
public:
	int _b = 2;
};

//相近类型(隐式类型)
void test_static_cast()
{
	
	double d = 10.5;
	int i = static_cast<int>(d);
	cout << i << endl;
}
//不相近类型(强转)
void test_reinterpret_cast()
{
	int *p = nullptr;
	int i = 10;
	p = (int*)i;
	cout << p << endl;
	p = reinterpret_cast<int*>(i);
	cout << p << endl;
}
//去除const属性,方便赋值
void test_const_cast()
{
	//const_cast
	int i1 = 10;
	int *p1 = const_cast<int*>(&i1);
	*p1 = 5;
	cout << "i1->" << i1 << " " << "*p1->" << *p1 << endl;
	//有const 的原来的值不变,因为const的值在寄存器(由于编译器优化)里面,而改掉的值是在内存里的
	const int i2 = 10;
	int *p2 = const_cast<int*>(&i2);
	*p2 = 5;
	cout << "i2->" << i2 << " " << "*p2->" << *p2 << endl;
	//volatile防止编译器优化
	volatile const int i3 = 10;
	int *p3 = const_cast<int*>(&i3);
	*p3 = 5;
	cout << "i3->" << i3 << " " << "*p3->" << *p3 << endl;
}

void fun(A* p)
{
	/*A* pa = p;
	pa->_a;
	//强转越界访问了
	B* pb = (B*)p;
	pb->_b;*/

	
	B* b = dynamic_cast<B*>(p);
	if (b)
		cout << "指向子类,转换成功" << endl;
	else
		cout << "指向父类,转换失败" << endl;
	
}
//多态类型的转换,(父类对象必须包换虚函数)
//dynamic_cast是到指针指向对象的虚表上方找到对象的标识信息
void test_dynamic_cast() 
{
	//子类对象给父类,切片
	A a;
	B b;

	A* pa = &a;
	fun(pa);

	pa = &b;
	fun(pa);

}
void test_cpp()
{
	//test_static_cast();
	//test_reinterpret_cast();
	//test_const_cast();
	//test_dynamic_cast();
}

class C
{
public:
	 explicit C(int c)
	{
		cout << "C(int c)" << endl;
	}
	C(const C& c)
	{
		cout << "C(const C& c)" << endl;
	}
private:
	int _a;
};
void  test_explicit()
{
	C c1(1);
	C c2(c1);

	//隐式类型转换,没写 = ,但是会隐式类型转换成 C tmp(1)-> C c3(tmp)从而构造出来c3
	//C c3 = 1;
	
}
int main()
{
	//test_c();
	//test_cpp();
	//test_explicit();
	system("pause");
	return 0;
}
5.心得体会

通过这个章节的学习,我对类型转换有了新的认识,我们写代码时一定要注重规范,这样才能高效。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值