数据类型转换
转换为最宽的数据类型
eg:
#include <iostream>
using std::cout;
using std::endl;
int main(int argc, char* argv[])
{
int ival = 3;
double dval = 3.14159;
cout << ival + dval << endl;//ival被提升为double类型
return 0;
}
其运行结果:
6.14159
int main(int argc, char* argv[])
{
010D17D0 push ebp
010D17D1 mov ebp,esp
010D17D3 sub esp,0DCh
010D17D9 push ebx
010D17DA push esi
010D17DB push edi
010D17DC lea edi,[ebp-0DCh]
010D17E2 mov ecx,37h
010D17E7 mov eax,0CCCCCCCCh
010D17EC rep stos dword ptr es:[edi]
int ival = 3;
010D17EE mov dword ptr [ival],3
double dval = 3.14159;
010D17F5 movsd xmm0,mmword ptr [__real@400921f9f01b866e (010D6B30h)]
010D17FD movsd mmword ptr [dval],xmm0
cout << ival + dval << endl;//ival被提升为double类型
010D1802 mov esi,esp
010D1804 push offset std::endl<char,std::char_traits<char> > (010D1064h)
010D1809 cvtsi2sd xmm0,dword ptr [ival]
010D180E addsd xmm0,mmword ptr [dval]
010D1813 mov edi,esp
010D1815 sub esp,8
010D1818 movsd mmword ptr [esp],xmm0
010D181D mov ecx,dword ptr [_imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A (010D90A8h)]
010D1823 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (010D90A0h)]
010D1829 cmp edi,esp
010D182B call __RTC_CheckEsp (010D111Dh)
010D1830 mov ecx,eax
010D1832 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (010D90A4h)]
010D1838 cmp esi,esp
010D183A call __RTC_CheckEsp (010D111Dh)
return 0;
010D183F xor eax,eax
}
010D1841 pop edi
}
010D1842 pop esi
010D1843 pop ebx
010D1844 add esp,0DCh
010D184A cmp ebp,esp
010D184C call __RTC_CheckEsp (010D111Dh)
010D1851 mov esp,ebp
010D1853 pop ebp
010D1854 ret
(2)赋值
转换为被赋值对象的类型,但不会改变赋值对象的数据类型。
eg:
#include <iostream>
using std::cout;
using std::endl;
int main(int argc, char* argv[])
{
int ival = 4;
double dval = 3.14159;
ival = dval; // double->int
cout << dval << endl;
cout << ival << endl;
return 0;
}
其运行结果:
3.14159
3
注意:数据类型窄化转换时,注意数据溢出及丢失。
#include <iostream>
using std::cout;
using std::endl;
double square(double dval);
int main(int argc, char* argv[])
{
cout << square(5) << endl;
return 0;
}
double square(double dval)
{
return dval * dval;
}
其运行结果:
25
当返回类型与表达式类型不同时,转换为返回类型。
eg:
#include <iostream>
using std::cout;
using std::endl;
double difference(int ival1, int ival2);
int main(int argc, char* argv[])
{
int ival1 = 2;
int ival2 = 3;
cout << difference(2, 3) << endl;
return 0;
}
double difference(int ival1, int ival2)
{
return ival1 - ival2; //返回值被提升为double类型
}
其运行结果:
-1
(1)单参数构造函数
// implicit conversion of classes:
#include <iostream>
using std::cout;
using std::endl;
class A {};
class B {
public:
// conversion from A (constructor)
B(const A& x)
{
cout << "Conversion from A (constructor)" << endl;
}
// conversion from A (assignment)
B& operator= (const A& x)
{
cout << "Conversion from A (assignment)" << endl;
return *this;
}
// conversion to A (type-cast operator)
operator A()
{
cout << "Conversion to A (type-cast operator)" << endl;
return A();
}
};
int main(int argc, char* argv[])
{
A foo;
B bar = foo; // calls constructor
bar = foo; // calls assignment
foo = bar; // calls type-cast operator
return 0;
}
其运行结果:
Conversion from A (constructor)
Conversion from A (assignment)
Conversion to A (type-cast operator)
1)C风格
eg:
#include <iostream>
using std::cout;
using std::endl;
int main(int argc, char* argv[])
{
int ival;
double dval = 3.14159;
ival = (int)dval; // double->int
cout << dval << endl;
cout << ival << endl;
return 0;
}
其运行结果:
3.14159
3
2)函数风格
dst = T(src)
eg:
#include <iostream>
using std::cout;
using std::endl;
int main(int argc, char* argv[])
{
int ival;
double dval = 3.14159;
ival = int(dval); // double->int
cout << dval << endl;
cout << ival << endl;
return 0;
}
其运行结果:
3.14159
3
3)
(1)static_casta、 类层次结构中基类和派生类之间指针或者引用的转换。up-casting (把派生类的指针或引用转换成基类的指针或者引用表示)是安全的;down-casting(把基类指针或引用转换成子类的指针或者引用)是不安全的。
b、基本数据类型之间的转换
c、把空指针转换成目标类型的空指针(null pointer)
d、 把任何类型的表达式转换成void类型
注意:不能转换掉表达式的const、volitale或者__unaligned属性。
eg1:
#include <iostream>
using std::cout;
using std::endl;
class Dummy
{
double i, j;
};
class Addition
{
int x, y;
public:
Addition(int a, int b) { x = a; y = b; }
int result() { return x + y; }
};
int main(int argc, char* argv[])
{
Dummy d;
Addition * padd;
padd = (Addition*)&d;
cout << padd->result();
return 0;
}
其运行结果:
-1717986920
不做类型检查,转换没有安全性
eg2:
#include <iostream>
using std::cout;
using std::endl;
class Dummy
{
double i, j;
};
class Addition
{
int x, y;
public:
Addition(int a, int b) { x = a; y = b; }
int result() { return x + y; }
};
int main(int argc, char* argv[])
{
Dummy d;
Addition * padd;
padd = static_cast<Addition*>(&d);
cout << padd->result();
return 0;
}
b、下行转换时,其具有类型转换的功能,比static_cast更安全;
c、交叉转换时,其转换成空指针,而static_cast则不允许转换。
注意:不能转换掉表达式的const、volitale或者__unaligned属性。
eg:
// dynamic_cast
#include <iostream>
#include <exception>
using std::cout;
using std::endl;
using std::exception;
class Base { virtual void dummy() {} };
class Derived : public Base { int a; };
int main(int argc, char* argv[])
{
try {
Base * pba = new Derived;
Base * pbb = new Base;
Derived * pd;
pd = dynamic_cast<Derived*>(pba);
if (pd == 0) cout << "Null pointer on first type-cast.\n";
pd = dynamic_cast<Derived*>(pbb);
if (pd == 0) cout << "Null pointer on second type-cast.\n";
}
catch (exception& e) { cout << "Exception: " << e.what(); }
return 0;
}
其运行结果:
Null pointer on second type-cast.
转换一个指针为其他类型的指针,也允许将一个指针转换为整数类型,反之亦然。这个操作符能够在非相关的类型之间进行转换。操作结果只是简单的从一个指针到别的指针的值的二进制拷贝,在类型之间指向的内容不做任何类型的检查和转换。这是一个强制转换。使用时有很大的风险,慎用之。
注意:不能转换掉表达式的const、volitale或者__unaligned属性。
eg1:
// expre_reinterpret_cast_Operator.cpp
// compile with: /EHsc
#include <iostream>
using std::cout;
using std::endl;
// Returns a hash code based on an address
unsigned short Hash(void *p)
{
unsigned int val = reinterpret_cast<unsigned int>(p);
return (unsigned short)(val ^ (val >> 16));
}
int main(int argc, char* argv[])
{
int a[20];
for (int i = 0; i < 20; i++)
cout << Hash(a + i) << endl;
}
其运行结果:
eg2:
#include <iostream>
struct Foo {};
struct Bar {};
int main()
{
Foo* f = new Foo;
Bar* b1 = f;
Bar* b2 = static_cast<Bar*>(f);
Bar* b3 = dynamic_cast<Bar*>(f);
Bar* b4 = const_cast<Bar*>(f);
Bar* b5 = reinterpret_cast<Bar*>(f);
return 0;
}
1>------ 已启动全部重新生成: 项目: test, 配置: Debug Win32 ------
1> main.cpp
1>f:\workspace\test\test\main.cpp(10): error C2440: “初始化”: 无法从“Foo *”转换为“Bar *”
1> f:\workspace\test\test\main.cpp(10): note: 与指向的类型无关;转换要求 reinterpret_cast、C 样式转换或函数样式转换
1>f:\workspace\test\test\main.cpp(11): error C2440: “static_cast”: 无法从“Foo *”转换为“Bar *”
1> f:\workspace\test\test\main.cpp(11): note: 与指向的类型无关;转换要求 reinterpret_cast、C 样式转换或函数样式转换
1>f:\workspace\test\test\main.cpp(12): error C2683: “dynamic_cast”:“Foo”不是多态类型
1> f:\workspace\test\test\main.cpp(3): note: 参见“Foo”的声明
1>f:\workspace\test\test\main.cpp(13): error C2440: “const_cast”: 无法从“Foo *”转换为“Bar *”
1> f:\workspace\test\test\main.cpp(13): note: 与指向的类型无关;转换要求 reinterpret_cast、C 样式转换或函数样式转换
========== 全部重新生成: 成功 0 个,失败 1 个,跳过 0 个 ==========
修改类型的const或volatile属性
a、常量指针被转化成非常量指针,转换后指针指向原来的变量(即转换后的指针地址不变)
eg1:
// const_cast
#include <iostream>
using std::cout;
using std::endl;
void print(char * str)
{
cout << str << endl;
}
int main(int argc, char* argv[])
{
const char * c = "sample text";
print(const_cast<char *> (c));
return 0;
}
其运行结果:
sample text
#include <iostream>
using std::cout;
using std::endl;
class A
{
public:
A()
{
m_iNum = 0;
}
int m_iNum;
};
int main(int argc, char* argv[])
{
//1、指针指向类
const A *pca1 = new A;
A *pa2 = const_cast<A*>(pca1); //常量对象转换为非常量对象
pa2->m_iNum = 200;
//转换后指针指向原来的对象
cout << pca1->m_iNum << " " << pa2->m_iNum << endl; //200 200
//2、指针指向基本类型
const int ica = 100;
int * ia = const_cast<int *>(&ica);
*ia = 200;
cout << *ia << " " << ica << endl; //200 100
return 0;
}
其运行结果:
200 200
200 100
eg:
#include <iostream>
using std::cout;
using std::endl;
class A
{
public:
A()
{
m_iNum = 1;
}
int m_iNum;
};
int main(int argc, char* argv[])
{
A a0;
const A &a1 = a0;
A a2 = const_cast<A&>(a1); //常量引用转为非常量引用
a2.m_iNum = 200;
cout << a0.m_iNum << endl;
cout << a1.m_iNum << endl;
cout << a2.m_iNum << endl;
return 0;
}
其运行结果:
1
1
200
#include <iostream>
using std::cout;
using std::endl;
class A
{
public:
A()
{
m_iNum = 1;
}
int m_iNum;
};
int main(int argc, char* argv[])
{
//常量对象被转换成非常量对象时出错
const A ca;
A a = const_cast<A>(ca); //不允许
const int i = 100;
int j = const_cast<int>(i); //不允许
return 0;
}
#include <iostream>
using std::cout;
using std::endl;
int main(int argc, char* argv[])
{
int i = 100;
int *j = &i;
const int *k = const_cast<const int*>(j);
//const int *m = j; 感觉和这样写差不多
//指的地址都一样
cout << i << "," << &i << endl;
cout << *j << "," << j << endl;
cout << *k << "," << k << endl;
*j = 200;
cout << i << "," << &i << endl;
cout << *j << "," << j << endl;
cout << *k << "," << k << endl;
return 0;
}
其运行结果:
参考文献
[1]static_cast,dynamic_cast,reinterpret_cast和const_cast的区别详解. http://www.jb51.net/article/41377.htm.
[2] static_cast,dynamic_cast, const_cast探讨. http://www.cnblogs.com/chio/archive/2007/07/18/822389.html.
[3]static_cast. http://baike.baidu.com/link?url=k_oO_od3IQcIQFhxs39iqAu5hU5AoT5rtAv5d2a6yXSSXCb8y0EIvnlT_vqR0fqpXReqsfqXan4-UPCTL6ZILK.
[4] reinterpret_cast.http://baike.baidu.com/link?url=Db0gF69eNavQmAJ_SjkD88t9s9bmEd1eHh8-pYezezH-Xl8wAGC3pK_Lx6pRlL4262m9tgT2FOQjiO6KjonqFq.
[5] 之四、static_cast. http://blog.csdn.net/jofranks/article/details/7828331.
[6] 之三、const_cast. http://blog.csdn.net/jofranks/article/details/7828326.
[7] 之二、static_cast和dynamic_cast、reinterpret_cast. http://blog.csdn.net/jofranks/article/details/7816046.
[8] 之五、dynamic_cast. http://blog.csdn.net/jofranks/article/details/7828335.
[9] 之六、reinterpret_cast. http://blog.csdn.net/jofranks/article/details/7828339.
[10]static_cast, dynamic_cast, reinterpret_cast, const_cast区别比较. http://www.cnblogs.com/jerry19880126/archive/2012/08/14/2638192.html.
[11]dynamic_cast Operator. https://msdn.microsoft.com/en-us/library/cby9kycs?f=255&MSPPError=-2147217396.
[12]static_cast Operator. https://msdn.microsoft.com/en-us/library/c36yw7x9.aspx?f=255&MSPPError=-2147217396.
[13] const_castOperator. https://msdn.microsoft.com/en-us/library/bz6at95h.aspx.
[14] reinterpret_castOperator. https://msdn.microsoft.com/en-us/library/e0w9f63b.aspx.
[15] Regularcast vs. static_cast vs. dynamic_cast [duplicate]. http://stackoverflow.com/questions/28002/regular-cast-vs-static-cast-vs-dynamic-cast.
[16] Typeconversions. http://www.cplusplus.com/doc/tutorial/typecasting/.
[17] C++dynamic_cast实现原理. http://blog.csdn.net/passion_wu128/article/details/38511957.
[18] TYPE CASTOPERATORS – 2016. http://www.bogotobogo.com/cplusplus/typecast.php.
[19] C++类型转换详解--const_cast. http://blog.csdn.net/lwbeyond/article/details/6213382.
注:为了便于自己学习,无心侵权,尽可能将所引用的文章列举出来;有些文章的内容可能会与原作重复度较高,还请谅解。如作者举报,愿意删除此文。