C++四种基本类型转换

1.static_cast

用法: static_cast<type_name> (expression)
说明:该运算符把expression转换为typen_name类型,static_cast在编译时使用类型信息执行转换,在转换执行必要的检测(诸如指针越界计算,类型检查等);但没有运行时类型检查来保证转换的安全性。
枚举是收到限制的整型,取值范围收到限制,枚举不能++
静态转换两者类型要兼容,而且不能去常性,但是可以加常性
无类型指针可以转成任意类型

基本类型转换

x = static_cast(a);只是将a转成这种类型

enum WeekType { sun = 0, mon = 1, ture = 2, wed = 3 };
int main()
{
	int a = 10;
	char ch = 'a';
	double dx = 12.23;
	//a = static_cast<int> (dx);
	ch = static_cast<char>(dx);
	WeekType x = sun;
	//x++;//error
	a = x;
	//x = a;//error
	x = static_cast<WeekType>(a);

	return 0;
}

x = static_cast(a);
静态转换这个不报错。x和a都是0
目的就是枚举类型的转为整型,不报错。
在这里插入图片描述

指针转换的限制

基本类型指针无法转化。
可以加常性,但是不能去常性,你要是可 去常性 const_cast干嘛??????

int main(){
	int a = 10;
	int* p = &a;
	int* s = static_cast<int*>(&a); 
	int* s = nullptr;
	const int* cp = static_cast<const int*>(&a);
	//char* chp = static_cast<char*>(&a);//error
	//s = static_cast<int*>(cp);//error;静态转换类型必须一致
	s = const_cast<int*>(cp);

}

左值转右值

int main() {
	int a = 10;
	int &x= a;//左值
 
	//int&& rx = a;//error
	int&& rx = static_cast<int&&>(a);
	return 0;
}

rx x 都是a的别名

上下行转换

继承关系:
不同类的指针还能用static_cast转换,但是下行转换没有意义。但是不报错,
但是,不同类对象只能大对象赋值小对象。就算是用static_cast 也会报错

class Object {
private:
int value; public:
	Object(int x = 0) : value(x) {
		cout << "Create Object: " << endl;
	}
	~Object() {
		cout << "Destory 0bject" << endl;
	}

};
class Base : public Object {
private: int num; public:
	Base(int x = 0) : Object(x + 10), num(x) {
		cout << "Create Base " << endl;
	}
	 ~Base() {
		cout << "Destroy Base" << endl;
	}

};
int main() {
	Object* op = nullptr;
	Base* bp = nullptr;
	Base base;
	Object obj;
	op = &obj;
	bp = &base;

	op = bp;
	//bp = op;//error

	op = static_cast<Object*>(&base);
	bp = static_cast<Base*>(&obj);
	return 0;
}
int main() {
	Object o(10);
	Base b(20);

	//b = static_cast<Base>(o);//err
	return 0;
}

bp = static_cast<Base*>(&obj);这里虽然可以编译,但是逻辑上是错误的,内存填充的是默认值,bp = op;//error这里直接就无法编译
上行转换安全,下行转换不安全

2.const_cast

用法:const_cast <type_name>(expression)
可以适用基本类型,也可以用在自己设计的类型
说明:该运算符用来修改类型的const或volatile属性。除了const或volatile修饰之外,typename和expression的类型是一样的。

去常性

特点:
1)用于去除变量的只读属性
2)强制转换的目标类型必须是指针或引用

int main() {
	int a = 10;
	const int* ap = &a;
	const int& ra = a;

	//int* ip = ap;
	//int& r = ra; 编译不通过

	int* ip = const_cast<int*>(ap);
	int& r = const_cast<int&>(ra);
}

const 编译时的替换

class Int {
private:
	int value;
public:
	Int(int x = 0) :value(x) {
		cout << "Create Int" << endl;
	}
	~Int() {	}
	void SetValue(int x) {
		value = x;
	}
	int GetValue() const { return value; }

};
int main() {
	const int ca = 10;
	int* cap = const_cast<int*>(&ca);
	*cap = 20;
	cout << ca << endl;

	const Int a(10);
	//Int* p = &a;//error
	cout << a.GetValue() << endl;;
	Int* p = const_cast<Int*>(&a);
	p->SetValue(100);
	cout << a.GetValue() << endl;

	Int& aa = const_cast<Int&>(a);
	aa.SetValue(200);
	cout << a.GetValue() << endl;
}

由于ca是常整型,但是在编译的时候,ca已经被替换成了10,虽然它确实是变成了20,但是打印的还是10
而Int就不一样了,是常对象,去常性后,就可以修改

在这里插入图片描述

3.reinterpret_cast

用法: reinpreter_cast <type_name>(expression)
说明: type_name必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针。类似C语言的强转。
特点:
不适用基本数据类型之间的转换
用于指针类型间的强制转换

指针类型间的强制转换

基本数据类型指针的转换,和非继承 关系的类指针的转换,但是不安全。


int main() {
	int a = 0x61626364;
	//char* p = &a;//error
	char* p =  reinterpret_cast<char*>(&a);
	cout << *p << endl;
	p += 1;
	cout << *p << endl;
	p += 1;
	cout << *p << endl;
	p += 1;
	cout << *p << endl;

	return 0;
}

p+1的能力跟指向的类型无关,根自己的类型有关
在这里插入图片描述

class Object {
private:
	int value;
public:
	Object(int x = 0) : value(x) { }
	~Object() {}
	int& Value() { return value; }
	const int& Value() const { return value; }
};

int main() {
	Object obj(10);
	int* p = reinterpret_cast<int*>(&obj);
	int& a = reinterpret_cast<int&>(obj);
	cout << obj.Value() << endl;
	*p = 100;
	cout << obj.Value() << endl;
	a = 200;
	cout << obj.Value() << endl;
	
	return 0;
}

在这里插入图片描述

对象和对象中的数据成员value是同一个地址

4 .dynamic_cast

语法: dynamic_cast <typen_ame> ( expression )
说明: dynamic_cast操作符,它允许在运行时刻进行类型转换,从而使程序能够在一个类层次结构中安全地转换类型,把基类指针转换成派生类指针,或把指向基类的左值转换成派生类的引用。
必须是公有继承,基类要有虚函数。
特点:
1.与C++支持的其他强制转换不同的是,dynamic_cast是在运行时执行的类型转换。
⒉.如果针对指针类型的dynamic_cast失败,则dynamic_cast的结果是nullptr。
3.如果针对引用类型的dynamic_cast失败,则dynamic_cast会抛出一个异常。
4.在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的。
5.在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。

初识动态转换

人家本来是基类的指针指向派生类对象,可以实现多态,可是用dynamic_cast将基类指针转成了派生类指针,多态性消失
只有dynamic_cast多态转换的对象必须要发生多态,否则返回为空

class Object {
private:
	int value;
public:
	Object(int x=0):value(x){}
	~Object(){}
	virtual void func() { cout << "virtual Object func" << endl; }
	void fun() { cout << "Object fun"<<endl; }
};
class Base :public Object {
private:
	int num;
public:

	Base(int x=0):Object(x),num(x+10){ }
	~Base(){}
	virtual void func(){ cout << "virtual Base func" << endl; }
	void fun() { cout << "Base fun" << endl; }
};

int main() {
	Object* op1 = nullptr, * op2 = nullptr;
	Object obj(10);
	Base* bp = nullptr;
	Base base(10);
	op1 = &base;
	op2 = &obj;

	op1->fun();
	op1->func();
	op2->fun();
	op2->func();

	bp = dynamic_cast<Base*>(op1);
	bp->fun();
	bp->func();
	return 0;
}

总结:
Object* op1 = nullptr, op1 = &base; op1在用静态函数时,他就是Object*, 但是有虚函数时,就是Base*,通过动态转换Base* bp = nullptr;, bp = dynamic_cast<Base*>(op1); op1在用静态函数时,和虚函数时,都就是Base*
在这里插入图片描述

验证多态才能实现动态转换


int main() {
	Object* op1 = nullptr, * op2 = nullptr;
	Object obj(10);
	Base* bp = nullptr;
	Base base(10);
	op1 = &base;
	op2 = &obj;
	//指针类型信息
	cout << typeid(op1).name() << endl;
	cout << typeid(op2).name() << endl;
	cout << typeid(*op1).name() << endl;
	cout << typeid(*op2).name() << endl;
	
	op1->fun();
	op1->func();
	op2->fun();
	op2->func();

	//op1指向&base,可以动态转换
	bp = dynamic_cast<Base*>(op1);
	bp->fun();
	bp->func();

	//op1指向&obj,不可以动态转换
	bp = dynamic_cast<Base*>(op2);
	if (bp == nullptr) {
		cout << "bp==nullptr" << endl;
	}
	else bp->func();
	return 0;
}

typeid(*op1).name() 能知道指针所指之物是存储了类型识别信息
在这里插入图片描述

反向 多态

这里下行转换,就不行
在这里插入图片描述

int main() {
	
	Object obj(10);
	Base* bp = nullptr;
	Base base(10);
	Object* op1 = &base;
	Object* op2 = &obj;
	//Base* bp1 = &obj;//err
	Base* bp1 = static_cast<Base*>(&obj);//作用就是编译通过 逻辑上不行
	Base* bp2 = &base;
	bp1->fun();
	bp1->func();
	bp2->fun();
	bp2->func();

	return 0;
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值