C++四种类型转化

static_cast

该运算符把expression转化为type_name类型,static_cast在编译时使用类型信息执行转换,在转换执行必要时的检测(如指针越界,类型检查),但没有运行时类型检查来保证转换的安全性

  • 用于基本类型检查,如把int转换为char,把int转换为enum
enum WeekType{sun=0,Mon=1,Tues=2,Wed=3,Thus=4,Fir=5,Sat=6};

int main()
{
	int a = 10;
	char ch = 'x';
	double dx = 12.34;
	a = static_cast<int>(ch);
	a = static_cast<int>(dx);
	WeekType x = Mon;
	a = x;
	x = static_cast<WeekType>(a);
}
  • 指针转换的限制
    在这里插入图片描述
  • 可以就void*转换为其它类型
int main()
{
	int a = 10;
	int* ip = nullptr;
	double* dp = nullptr;
	void* vp = &a;
	ip = static_cast<int*>(vp);
	dp = static_cast<double*>(dp);
	return 0;
}
  • 弃值表达式
int main()
{
	int a = 10, b = 20;
	static_cast<void>(a + b);
}

  • 左值到右值
    1.先补充一个小知识点,移动语义
class PtrInt
{
private:
	int* pval; // new .heap ; stack . data;
public:
	PtrInt(int* p = nullptr) :pval(p)
	{
		cout << "create Ptrint:" << this << endl;
	}
	~PtrInt()
	{
		delete pval;
		pval = nullptr;
		cout << "Destory Ptrin:t" << this << endl;
	}
	PtrInt(const PtrInt& it) :pval(new int(0)) //拷贝构造函数
	{
		*pval = *it.pval;
		//*pval = it.*pval;
	}
	PtrInt& operator=(const PtrInt& it) //拷贝赋值函数
	{
		if (this != &it)
		{
			delete pval;
			pval = new int(*it.pval);
			//pval = it.pval;
		}
		cout << "Copy create Ptrint:" << this << endl;
		return *this;
	}
	PtrInt(PtrInt&& it) :pval(it.pval) //移动构造函数
	{
		it.pval = nullptr;
		cout << "move copy create Ptrint:" << this << endl;
	}
	PtrInt& operator=(PtrInt&& it) //移动赋值函数
	{
		if (this != &it)
		{
			delete[]pval;
			pval = it.pval;
			it.pval = nullptr;
		}
		cout << "Copy operator Ptrint:" << this << endl;
		return *this;
	}
};

PtrInt func(int x)
{
	PtrInt tmp(new int(x));
	return tmp;
}

int main()
{
	PtrInt a(new int(10));
	a = func(100);
	return 0;
}

在这里插入图片描述
运行结果:
在这里插入图片描述
2.左值与右值之间的转换

#include<iostream>
using namespace std;
class PtrInt
{
private:
 int* pval; // new .heap ; stack . data;
public:
 PtrInt(int* p = nullptr) :pval(p) 
 {
 }
 ~PtrInt() 
 { 
  delete pval; 
  pval = nullptr;
 }
 PtrInt(const PtrInt& it) :pval(new int(0)) //拷贝构造函数
 {
  *pval = *it.pval;
  //*pval = it.*pval;
 }
 PtrInt& operator=(const PtrInt& it) //拷贝赋值函数
 {
  if (this != &it)
  {
   delete pval;
   pval = new int(*it.pval);
   //pval = it.pval;
  }
  return *this;
 }
 PtrInt(PtrInt&& it):pval(it.pval) //移动构造函数
 {
  it.pval = nullptr;
 } 
 PtrInt& operator=(PtrInt&& it) //移动赋值函数
 {
  if (this != &it)
  {
   delete[]pval;
   pval = it.pval;
   it.pval = nullptr;
  }
  return *this;
 }
};

int main()
{
 const PtrInt a(new int(10)), b(new int(20)), c(new int(30));
 PtrInt x(a);
 PtrInt aa((PtrInt&&)a); //耍流氓行为,直接强转,不会报错
 //PtrInt bb(static_cast<PtrInt&&>(b)); //会报错,不能实现常对象的转换
 PtrInt bb(static_cast<PtrInt&&>(const_cast<PtrInt&>(b)));
 PtrInt cc(std::move(c)); //移动语义,此时常对象,调用的是拷贝构造函数
 return 0;
}
  • 用于类层次结构中的基类和派生类之间指针和引用的转化(上行转换是安全的,下行转换由于没有动态类型检查,是不安全的)
class object
{
private:
	int value;
public:
	object(int x = 0) :value(x) {}
	void func() {}
};
class Base :public object
{
private:
	int num;
public:
	Base(int x=0):object(x+10),num(x){}
	void show()const{}
};
int main()
{
	object* op = nullptr;
	Base* bp = nullptr;
	Base base;
	object obj;
	op = &obj;
	bp = &base;
	op = static_cast<object*>(&base);
	bp = static_cast<Base*>(&obj);
	return 0;
}

const_cast

  • 用于去除变量的只读属性
  • 强制转换的目标必须是指针或者引用
int main()
{
	const int a = 10;
	const int* cp = &a;
	const int& cr = a;
	int* p = const_cast<int*>(cp);
	int& r = const_cast<int&>(cr);
	int&& rr = const_cast<int&&>(a);
	return 0;
}

class Int
{
	int value;
public:
	Int(int x = 0) :value(x) {}
	~Int() {}
	void SetValue(int x) { value = x; }
	int GetValue()const { return value; }
};

int main()
{
	const Int a(10);
	cout << a.GetValue() << endl;
	Int* ip = const_cast<Int*>(&a);
	Int& b = const_cast<Int&>(a);

	ip->SetValue(100);
	cout << a.GetValue() << endl;
	b.SetValue(200);
	cout << a.GetValue() << endl;
}

reinterpret_cast(重新解释)

有点类似于C语言的强转
特点:
用于指针类型间强制转化
用于整数和指针类型间的强制转化

int main()
{
	int a = 0x6162634;
	char* cp = reinterpret_cast<char*>(&a);
	cout << *cp << endl;
	cp += 1;
	cout << *cp << endl;
	cp += 1;
	cout << *cp << endl;
	cp += 1;
	cout << *cp << endl;
	cp += 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);
	*p = 100;
	cout << obj.Value() << endl;
	a += 100;
	cout << obj.Value() <<endl;
	return 0;
}

dynamic_cast

必须是公有继承,基类要有虚函数
1.与C++支持其他强制转化的不同的是,dynamic_cast是在运行时执行的动态类型转换
2.如果针对指针类型的dynamic_cast失败,则dynamic_cast的结果是nullptr
3.如果针对引用类型的dynamic_cast失败,则dynamic_cast会抛出一个异常
4.在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的
5.在进行下行转换时,dynamic_cast具有类型检查功能,比static_cast更安全
6.上行转换如果没有虚函数,都属于静态类型转换
7.dynamic_cast的操作数必须是指向完整类类型的指针

//上相转换
class object
{
private:
	int value;
public:
	object(int x = 0) :value(x) {}
	void func() { cout << "value" << value << endl; }
};
class Base :public object
{
private:
	int num;
public:
	Base(int x = 0) :object(x + 10), num(x) {}
	void show()const { void func() { cout << "num" <<num << endl; } }
};

int main()
{
	object* op = nullptr;
	object obj(10);
	Base base(10);
	op = &obj;
	op = &base;
	op = dynamic_cast<object*>(&base);
	op = static_cast<object*>(&base);
}

指针类型转换

//下行转换
class object
{
private:
	int value;
public:
	object(int x = 0) :value(x) {}
	virtual void func() { cout << "value" << value << endl; }
};
class Base :public object
{
private:
	int num;
public:
	Base(int x = 0) :object(x + 10), num(x) {}
	void func() { cout << "num" << num << endl; } 
};

int main()
{
	Base base;
	object* pobj = &base;
	Base* pa = dynamic_cast<Base*>(pobj);
	Base* pb = static_cast<Base*>(pobj);

	object obj;
	pobj = &obj;
	pb = static_cast<Base*>(pobj);
	pb->func();
	pa = dynamic_cast<Base*>(pobj);//动态转换  pa=nullptr
	pa->func();  //报错,转化的时候检查RTTI,运行时类型识别信息
	
}

在这里插入图片描述

引用类型转换

//下行转换
class Object
{
private:
	int value;
public:
	Object(int x = 0) :value(x) {}
	virtual void func() { cout << "value" << value << endl; }
};
class Base :public Object
{
private:
	int num;
public:
	Base(int x = 0) :Object(x + 10), num(x) {}
	void func() { cout << "num" << num << endl; } 
};

int main()
{
	Object object;
	Base base;
	Object& obj = object;

	try
	{
		Base& ba = dynamic_cast<Base&>(obj);
		ba.func();
	}
	catch (std::bad_cast& x)
	{
		cout << x.what() << endl;
	}
	return 0;
}

运行结果:
在这里插入图片描述
3.关于RTTI的用途以及根据动态类型进行分类

class Goods
{
 float _weight;  // 重量
public:
 Goods(float wt) : _weight(wt) {}
 virtual ~Goods() { std::cout << "~Trash()" << std::endl; }
 float GetWeight() const { return _weight; }
 virtual float GetPrice() const = 0;  // 价格
};

// 铜
class Copper : public Goods
{
 static float price;
public:
 Copper(float wt) : Goods(wt) {}
 float GetPrice() const { return price ; }
 static void SetPrice(float newprice) {
  price = newprice;
 }
};
float Copper::price = 2.80;

// 纸张
class Paper : public Goods
{
 static float price;
public:
 Paper(float wt) : Goods(wt) {}
 float GetPrice() const { return price ; }
 static void SetPrice(float newprice) {
  price = newprice;
 }
};
float Paper::price = 0.20;

// 玻璃
class Glass : public Goods
{
 static float price;
public:
 Glass(float wt) : Goods(wt) {}
 float GetPrice() const { return price ; }
 static void SetPrice(float newprice) {
  price = newprice;
 }
};
float Glass::price = 0.32;

template<class Container >
void sumPrice(Container& bin)
{
 float total = 0;
 for (auto p : bin)
 {
  //cout << typeid(x).name() << endl;
  total += p->GetPrice() * p->GetWeight();
  cout << "wight of : " << typeid(*p).name() << " = " << p->GetWeight() << endl;
 }
 cout << "Total price = " << total << endl;
}

int main()
{
 srand(time(0)); // Seed the random number generator
 vector<Goods*> bin;
 int n = rand() % 200;  // 0 199
 for (int i = 0; i < n; i++)
 {
  switch (rand() % 3)
  {
  case 0:
   bin.push_back(new Copper((rand() % 1000) / 10.0));
   break;
  case 1:
   bin.push_back(new Paper((rand() % 1000) / 10.0));
   break;
  case 2:
   bin.push_back(new Glass((rand() % 1000) / 10.0));
   break;
  }
 }
 // Note: bins hold exact type of object, not base type:
 vector<Glass*> glassBin;
 vector<Paper*> paperBin;
 vector<Copper*> coppBin;
 vector<Goods*>::iterator sorter = bin.begin();
 // Sort the Trash:
 while (sorter != bin.end())
 {
  Copper* cp = dynamic_cast<Copper*>(*sorter);
  Paper* pa = dynamic_cast<Paper*>(*sorter);
  Glass* gp = dynamic_cast<Glass*>(*sorter);
  if (cp) coppBin.push_back(cp);
  else if (pa) paperBin.push_back(pa);
  else if (gp) glassBin.push_back(gp);
  ++sorter;
 }
 sumPrice(coppBin);
 sumPrice(paperBin);
 sumPrice(glassBin);
 sumPrice(bin);
 for (auto& x : bin)
 {
  delete x;
  x = nullptr;
 }
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淡蓝色的经典

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值