<C/C++> 类型转换

变量进行操作的时候要求类型,函数调用的时候要求实参类型与形参相同。此时就涉及到了类型转换。

类型转换分为隐式转换和显式转换。

1. 隐式转换

顾名思义,非人为控制的,编译器进行的类型转换,此种情况下程序员可能并不知道进行了转换。

如:

int i = 10;
i += 10.23;		//要求加数也是int型,常数10.23默认为double型,隐式转换为int, 值截断变为10
编译时编译器也会提醒“ warning C4244: “+=”: 从“double”转换到“int”,可能丢失数据”, 因为8个字节的double型转换为4字节的int型时,会丢失高位的4个字节。

又如:

void PrintString(string str)
{
	cout << str << endl;
}

 
void TestCast()
{
	PrintString("mystring");  // "mystring"隐式转换为了string类型的临时局部变量
}
调用PrintString的时候,"mystring"作为string构造函数string(const char *)的实参初始化str。

2. 显式转换

将变量转换为指定的类型,即为显式转换。

C的风格,静态类型转换,比如:

(转换的类型)原类型的变量

void TestCast()
{
	int i = 10;
	int j = 0x10000;

	short s = (short)i;		// 编译器将不会提示数据截断,s的值与i相同
	short u = (short)j;		// 数据将发生截断: j的低位4个字节将赋值u,u的值将会是0,安全性需要程序员自己掌握

	cout << "s: " << s << endl;
	cout << "u: " << u << endl;

	char *pNewBuf = (char *)malloc(1024);	// malloc返回void *,将其转换为char *
        delete pNewBuf;
}

C++中,C的模式仍然可以使用,对struct,  class等也适用。

并提供了更加安全的转换操作符: static_cast、dynamic_cast、const_cast和reinterpret_cast。
const_cast,字面上理解就是去const属性。
static_cast,命名上理解是静态类型转换。如int转换成char。
dynamic_cast,命名上理解是动态类型转换。如子类和父类之间的多态类型转换。
reinterpreter_cast,仅仅重新解释类型,但没有进行二进制的转换。

转换的格式形如:static_cast<newtype>(var)

const_cast: 去除const\volatile属性

void PrintCString(char *sz)
{
	cout << sz << endl;
}

void TestCast()
{
	const char *cpstr = "this is const string for const_cast";

	// PrintCString(cpstr); // 系统提示error C2664: “PrintCString”: 不能将参数 1 从“const char *”转换为“char *”
	char *pstr = const_cast<char *>(cpstr); // 类似于 pstr = (char *)cpstr;
	PrintCString(pstr);
	
}


reinterpreter_cast: 重新解释类型

仅仅复制了比特位,而没有进行分析。谨慎使用。(参看链接

void TestCast()
{
	const char *cpstr = "this is const string for const_cast";
	
	int nPtrAddr = reinterpret_cast<int>(cpstr); // cpstr的值转换为int值
	cout << hex << uppercase <<  showbase << nPtrAddr << endl;  // 显示为大写的十六进制
}

static_cast: 类似于C风格的强制转换。无条件转换,静态类型转换

1. 基类和子类之间转换:其中子类指针转换成父类指针是安全的;但父类指针转换成子类指针是不安全的。(基类和子类之间的动态类型转换建议用dynamic_cast)
2. 基本数据类型转换。enum, struct, int, char, float等。static_cast不能进行无关类型(如非基类和子类)指针之间的转换。
3. 把空指针转换成目标类型的空指针。
4. 把任何类型的表达式转换成void类型。
5. static_cast不能去掉类型的const、volitale属性(用const_cast)。

class A
{
public:
	virtual void Print() { cout<<"This is class A."<<endl; }
};

class B : public A
{
public:
	void Print() { cout<<"This is class B."<<endl; }
};

class C
{

};

class D : public C
{

};

int ival = 0x10000;
short sval = static_cast<short>(ival);		// 依旧会截断

D vd;
C *pC = static_cast<C *>(&vd);		// 适用于没有虚函数的类
//pC = static_cast<C *>(&ival);		// error: “static_cast”: 无法从“int *”转换为“C *”

B b;
A *pA = static_cast<A *>(&b);

dynamic_cast: 有条件转换,动态类型转换,运行时类型安全检查(转换失败返回NULL):
1. 安全的基类和子类之间转换。
2. 必须要有虚函数。
3. 相同基类不同子类之间的交叉转换。但结果是NULL。

class E : public A
{
public:
	void Print() { cout<<"This is class E."<<endl; }

};

class F : public E, public B
{
public:
	void Print() { cout<<"This is class F."<<endl; }

};

D d;
C *pC = dynamic_cast<C *>(&d);		// 类C/D没有虚函数, 正常转换


B b;
A *pA = dynamic_cast<A *>(&b);		// 正常转换


A a;
B *pB = dynamic_cast<B *>(&a);		// pB将会是NULL
A &rA = dynamic_cast<A&>(a);		// okay
rA.Print();

try{
	B &rB = dynamic_cast<B&>(rA);		// 将抛出bad_cast异常
	rB.Print();
}
catch (std::bad_cast bc)
{
	cout << bc.what() << endl;
}

//
/*       F
	/ \
	E   B
	\  /
	 A
*/

F f;
A *pA2 = dynamic_cast<A *>(&f);  // dynamic_cast 用于转换为不可访问或不明确的基;运行时测试将失败(“F *”到“A *”)


总结:
去const属性用const_cast。
基本类型转换用static_cast。
多态类之间的类型转换用daynamic_cast。
不同类型的指针类型转换用reinterpreter_cast。(危险操作)


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值