数据类型转换.docx
《数据类型转换.docx》由会员分享,可在线阅读,更多相关《数据类型转换.docx(23页珍藏版)》请在冰点文库上搜索。
数据类型转换
数据类型转换
一、隐式类型转换
1)简单数据类型
(1)算术运算
转换为最宽的数据类型
eg:
[cpp]viewplaincopy
#include
usingstd:
:
cout;
usingstd:
:
endl;
intmain(intargc,char*argv[])
{
intival=3;
doubledval=3.14159;
cout<return0;
}
其运行结果:
6.14159
intmain(intargc,char*argv[])
{
010D17D0pushebp
010D17D1movebp,esp
010D17D3subesp,0DCh
010D17D9pushebx
010D17DApushesi
010D17DBpushedi
010D17DCleaedi,[ebp-0DCh]
010D17E2movecx,37h
010D17E7moveax,0CCCCCCCCh
010D17ECrepstosdwordptres:
[edi]
intival=3;
010D17EEmovdwordptr[ival],3
doubledval=3.14159;
010D17F5movsdxmm0,mmwordptr[__real@400921f9f01b866e(010D6B30h)]
010D17FDmovsdmmwordptr[dval],xmm0
cout<010D1802movesi,esp
010D1804pushoffsetstd:
:
endl:
char_traits>(010D1064h)
010D1809cvtsi2sdxmm0,dwordptr[ival]
010D180Eaddsdxmm0,mmwordptr[dval]
010D1813movedi,esp
010D1815subesp,8
010D1818movsdmmwordptr[esp],xmm0
010D181Dmovecx,dwordptr[_imp_?
cout@std@@3V?
$basic_ostream@DU?
$char_traits@D@std@@@1@A(010D90A8h)]
010D1823calldwordptr[__imp_std:
:
basic_ostream:
char_traits>:
:
operator<<(010D90A0h)]
010D1829cmpedi,esp
010D182Bcall__RTC_CheckEsp(010D111Dh)
010D1830movecx,eax
010D1832calldwordptr[__imp_std:
:
basic_ostream:
char_traits>:
:
operator<<(010D90A4h)]
010D1838cmpesi,esp
010D183Acall__RTC_CheckEsp(010D111Dh)
return0;
010D183Fxoreax,eax
}
010D1841popedi
}
010D1842popesi
010D1843popebx
010D1844addesp,0DCh
010D184Acmpebp,esp
010D184Ccall__RTC_CheckEsp(010D111Dh)
010D1851movesp,ebp
010D1853popebp
010D1854ret
(2)赋值
转换为被赋值对象的类型,但不会改变赋值对象的数据类型。
eg:
[cpp]viewplaincopy
#include
usingstd:
:
cout;
usingstd:
:
endl;
intmain(intargc,char*argv[])
{
intival=4;
doubledval=3.14159;
ival=dval;//double->int
cout<cout<return0;
}
其运行结果:
3.14159
3
注意:
数据类型窄化转换时,注意数据溢出及丢失。
(3)函数传参
当实参与形参数据类型不同时,转换为形参数据类型。
eg:
[cpp]viewplaincopy
#include
usingstd:
:
cout;
usingstd:
:
endl;
doublesquare(doubledval);
intmain(intargc,char*argv[])
{
cout<return0;
}
doublesquare(doubledval)
{
returndval*dval;
}
其运行结果:
25
(4)函数返回
当返回类型与表达式类型不同时,转换为返回类型。
eg:
[cpp]viewplaincopy
#include
usingstd:
:
cout;
usingstd:
:
endl;
doubledifference(intival1,intival2);
intmain(intargc,char*argv[])
{
intival1=2;
intival2=3;
cout<return0;
}
doubledifference(intival1,intival2)
{
returnival1-ival2;//返回值被提升为double类型
}
其运行结果:
-1
2)类类型
(1)单参数构造函数
(2)赋值操作符
(3)类型转换操作符
eg:
[cpp]viewplaincopy
//implicitconversionofclasses:
#include
usingstd:
:
cout;
usingstd:
:
endl;
classA{};
classB{
public:
//conversionfromA(constructor)
B(constA&x)
{
cout<<"ConversionfromA(constructor)"<}
//conversionfromA(assignment)
B&operator=(constA&x)
{
cout<<"ConversionfromA(assignment)"<return*this;
}
//conversiontoA(type-castoperator)
operatorA()
{
cout<<"ConversiontoA(type-castoperator)"<returnA();
}
};
intmain(intargc,char*argv[])
{
Afoo;
Bbar=foo;//callsconstructor
bar=foo;//callsassignment
foo=bar;//callstype-castoperator
return0;
}
其运行结果:
ConversionfromA(constructor)
ConversionfromA(assignment)
ConversiontoA(type-castoperator)
二、显示类型转换
1)C风格
dst=(T)src
eg:
[cpp]viewplaincopy
#include
usingstd:
:
cout;
usingstd:
:
endl;
intmain(intargc,char*argv[])
{
intival;
doubledval=3.14159;
ival=(int)dval;//double->int
cout<cout<return0;
}
其运行结果:
3.14159
3
2)函数风格
dst=T(src)
eg:
[cpp]viewplaincopy
#include
usingstd:
:
cout;
usingstd:
:
endl;
intmain(intargc,char*argv[])
{
intival;
doubledval=3.14159;
ival=int(dval);//double->int
cout<cout<return0;
}
其运行结果:
3.14159
3
3)
(1)static_cast
a、类层次结构中基类和派生类之间指针或者引用的转换。
up-casting(把派生类的指针或引用转换成基类的指针或者引用表示)是安全的;down-casting(把基类指针或引用转换成子类的指针或者引用)是不安全的。
b、基本数据类型之间的转换
c、把空指针转换成目标类型的空指针(nullpointer)
d、把任何类型的表达式转换成void类型
注意:
不能转换掉表达式的const、volitale或者__unaligned属性。
eg1:
[cpp]viewplaincopy
#include
usingstd:
:
cout;
usingstd:
:
endl;
classDummy
{
doublei,j;
};
classAddition
{
intx,y;
public:
Addition(inta,intb){x=a;y=b;}
intresult(){returnx+y;}
};
intmain(intargc,char*argv[])
{
Dummyd;
Addition*padd;
padd=(Addition*)&d;
cout<result();
return0;
}
其运行结果:
-1717986920
不做类型检查,转换没有安全性
eg2:
[cpp]viewplaincopy
#include
usingstd:
:
cout;
usingstd:
:
endl;
classDummy
{
doublei,j;
};
classAddition
{
intx,y;
public:
Addition(inta,intb){x=a;y=b;}
intresult(){returnx+y;}
};
intmain(intargc,char*argv[])
{
Dummyd;
Addition*padd;
padd=static_cast(&d);
cout<result();
return0;
}
(2)dynamic_cast
转换类型与表达式类型相同,必须同时是类的指针、类的引用或void*.用于类的上行、下行及交叉转换。
一般情况下,dynamic_cast用于具有多态性的类(即有虚函数的类)的类型转换。
a、上行转换时,其与static_cast效果相同;
b、下行转换时,其具有类型转换的功能,比static_cast更安全;
c、交叉转换时,其转换成空指针,而static_cast则不允许转换。
注意:
不能转换掉表达式的const、volitale或者__unaligned属性。
eg:
[cpp]viewplaincopy
//dynamic_cast
#include
#include
usingstd:
:
cout;
usingstd:
:
endl;
usingstd:
:
exception;
classBase{virtualvoiddummy(){}};
classDerived:
publicBase{inta;};
intmain(intargc,char*argv[])
{
try{
Base*pba=newDerived;
Base*pbb=newBase;
Derived*pd;
pd=dynamic_cast(pba);
if(pd==0)cout<<"Nullpointeronfirsttype-cast.\n";
pd=dynamic_cast(pbb);
if(pd==0)cout<<"Nullpointeronsecondtype-cast.\n";
}
catch(exception&e){cout<<"Exception:
"<return0;
}
其运行结果:
Nullpointeronsecondtype-cast.
(3)reinterpret_cast
转换一个指针为其他类型的指针,也允许将一个指针转换为整数类型,反之亦然。
这个操作符能够在非相关的类型之间进行转换。
操作结果只是简单的从一个指针到别的指针的值的二进制拷贝,在类型之间指向的内容不做任何类型的检查和转换。
这是一个强制转换。
使用时有很大的风险,慎用之。
注意:
不能转换掉表达式的const、volitale或者__unaligned属性。
eg1:
[cpp]viewplaincopy
//expre_nterpret_cast_Operator.cpp
//compilewith:
/EHsc
#include
usingstd:
:
cout;
usingstd:
:
endl;
//Returnsahashcodebasedonanaddress
unsignedshortHash(void*p)
{
unsignedintval=reinterpret_cast(p);
return(unsignedshort)(val^(val>>16));
}
intmain(intargc,char*argv[])
{
inta[20];
for(inti=0;i<20;i++)
cout<}
eg2:
[cpp]viewplaincopy
#include
structFoo{};
structBar{};
intmain()
{
Foo*f=newFoo;
Bar*b1=f;
Bar*b2=static_cast(f);
Bar*b3=dynamic_cast(f);
Bar*b4=const_cast(f);
Bar*b5=reinterpret_cast(f);
return0;
}
1>------已启动全部重新生成:
项目:
test,配置:
DebugWin32------
1>main.cpp
1>f:
\workspace\test\test\main.cpp(10):
errorC2440:
“初始化”:
无法从“Foo*”转换为“Bar*”
1>f:
\workspace\test\test\main.cpp(10):
note:
与指向的类型无关;转换要求reinterpret_cast、C样式转换或函数样式转换
1>f:
\workspace\test\test\main.cpp(11):
errorC2440:
“static_cast”:
无法从“Foo*”转换为“Bar*”
1>f:
\workspace\test\test\main.cpp(11):
note:
与指向的类型无关;转换要求reinterpret_cast、C样式转换或函数样式转换
1>f:
\workspace\test\test\main.cpp(12):
errorC2683:
“dynamic_cast”:
“Foo”不是多态类型
1>f:
\workspace\test\test\main.cpp(3):
note:
参见“Foo”的声明
1>f:
\workspace\test\test\main.cpp(13):
errorC2440:
“const_cast”:
无法从“Foo*”转换为“Bar*”
1>f:
\workspace\test\test\main.cpp(13):
note:
与指向的类型无关;转换要求reinterpret_cast、C样式转换或函数样式转换
==========全部重新生成:
成功0个,失败1个,跳过0个==========
(4)const_cast
修改类型的const或volatile属性
a、常量指针被转化成非常量指针,转换后指针指向原来的变量(即转换后的指针地址不变)
eg1:
[cpp]viewplaincopy
//const_cast
#include
usingstd:
:
cout;
usingstd:
:
endl;
voidprint(char*str)
{
cout<}
intmain(intargc,char*argv[])
{
constchar*c="sampletext";
print(const_cast(c));
return0;
}
其运行结果:
sampletext
eg2:
[cpp]viewplaincopy
#include
usingstd:
:
cout;
usingstd:
:
endl;
classA
{
public:
A()
{
m_iNum=0;
}
intm_iNum;
};
intmain(intargc,char*argv[])
{
//1、指针指向类
constA*pca1=newA;
A*pa2=const_cast(pca1);//常量对象转换为非常量对象
pa2->m_iNum=200;
//转换后指针指向原来的对象
cout<m_iNum<<""<m_iNum<//2、指针指向基本类型
constintica=100;
int*ia=const_cast(&ica);
*ia=200;
cout<<*ia<<""<return0;
}
其运行结果:
200200
200100
b、常量引用转为非常量引用
eg:
[cpp]viewplaincopy
#include
usingstd:
:
cout;
usingstd:
:
endl;
classA
{
public:
A()
{
m_iNum=1;
}
intm_iNum;
};
intmain(intargc,char*argv[])
{
Aa0;
constA&a1=a0;
Aa2=const_cast(a1);//常量引用转为非常量引用
a2.m_iNum=200;
cout<cout<cout<return0;
}
其运行结果:
1
1
200
c、常量对象(或基本类型)不可以被转换成非常量对象(或基本类型)
eg:
[cpp]viewplaincopy
#include
usingstd:
:
cout;
usingstd:
:
endl;
classA
{
public:
A()
{
m_iNum=1;
}
intm_iNum;
};
intmain(intar