Last active
February 28, 2018 11:20
-
-
Save lixingcong/21db1f1f0ce357215af424a052e3b2a8 to your computer and use it in GitHub Desktop.
Cast in C++
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
static_cast<type>(var) 静态类型转换,编译的时c++编译器会做类型检查 | |
基本类型(int,float...void*)能转换,通过继承关系的类之间也能相互转换 | |
但是不能转换不同指针类型 | |
*/ | |
#include <iostream> | |
using namespace std; | |
struct S1{ | |
int a,b; | |
char c[2]; | |
}; | |
class C1 { | |
public: | |
virtual ~C1(){} | |
virtual void f(){cout<<"I am C1"<<endl;} | |
}; | |
class C2: public C1 { | |
public: | |
virtual void f(){cout<<"I am C2"<<endl;} | |
}; | |
int main(int argc, char **argv) { | |
int i; | |
double d; | |
char c; | |
i=65; | |
cout<<"i="<<i<<endl; | |
cout<<endl; | |
// 隐式转换 | |
c=i; | |
d=i; | |
// ------- | |
d+=0.5; | |
cout<<"Implicit converting"<<endl; | |
cout<<"c="<<c<<endl; | |
cout<<"d="<<d<<endl; | |
cout<<endl; | |
// 使用static_cast进行C++风格的基本数据类型显式转换 | |
c=static_cast<char>(i); | |
d=static_cast<double>(i); | |
// ---------------------------------------------- | |
d+=0.5; | |
cout<<"Explicit converting (int -> char, int -> double)"<<endl; | |
cout<<"c="<<c<<endl; | |
cout<<"d="<<d<<endl; | |
cout<<endl; | |
S1 s1; | |
s1.a=100; | |
// 使用static_cast进行C++风格的void*显式转换 | |
void* p_s1_void=static_cast<void*>(&s1); | |
S1* p_s1=static_cast<S1*>(p_s1_void); | |
// -------------------------------------- | |
cout<<"Explicit converting (S1* -> void* -> S1*)"<<endl; | |
cout<<"p_s1->a="<<p_s1->a<<endl; | |
cout<<endl; | |
C2* c2=new C2; | |
// 使用static_cast进行C++风格的继承关系类之间显式转换 | |
// 可以子类与基类相互指向,这里仅演示基类指针指向子类 | |
C1* c1=static_cast<C1*>(c2); | |
// -------------------------------------- | |
cout<<"Explicit converting (C2* -> C1*)"<<endl; | |
c1->f(); | |
delete c2; | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
不同类型之间,进行强制类型转换,用reinterpret_cast<>() 进行重新解释 | |
reinterpret_cast<>()很难保证移植性(数据大小端问题) | |
*/ | |
#include <iostream> | |
using namespace std; | |
struct S1{ | |
int a,b; | |
char c[2]; | |
}; | |
struct S2{ | |
int a,b; | |
short c; | |
}; | |
int main(int argc, char **argv) { | |
char buffer[]="aaaa"; | |
cout<<"Explicit converting (char* -> short*)"<<endl; | |
short* p_short=reinterpret_cast<short*>(buffer); | |
cout<<"buffer="<<buffer<<endl; | |
cout<<"*p_short="<<*p_short<<endl; | |
cout<<endl; | |
S1* s1=new S1; | |
s1->c[0]='A'; | |
s1->c[1]='\0'; | |
cout<<"Explicit converting (S1* -> S2*)"<<endl; | |
S2* s2=reinterpret_cast<S2*>(s1); | |
cout<<"s1->c="<<s1->c<<endl; | |
cout<<"s2->c="<<s2->c<<endl; | |
cout<<endl; | |
delete s1; | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
动态类型转换,安全的基类和子类之间转换;运行时类型检查 | |
*/ | |
#include <iostream> | |
using namespace std; | |
class C1 { | |
public: | |
virtual ~C1(){} | |
}; | |
class C2: public C1 { | |
int a; | |
}; | |
const char HAVE[]="has"; | |
const char HAVENOT[]="doesn't have"; | |
int main(int argc, char **argv) | |
{ | |
C1* c1 = new C1; | |
C2* c2 = new C2; | |
C2* c2_xxx; | |
try{ | |
const char* does_have; | |
c2_xxx = dynamic_cast<C2*>(c1); | |
does_have=(nullptr != c2_xxx)?HAVE:HAVENOT; | |
cout << "c1 "<< does_have <<" type of C2.\n"; | |
c2_xxx = dynamic_cast<C2*>(c2); | |
does_have=(nullptr != c2_xxx)?HAVE:HAVENOT; | |
cout << "c2 "<< does_have <<" type of C2.\n"; | |
} catch (exception& e){ | |
cout << "Exception: " << e.what(); | |
} | |
delete c1; | |
delete c2; | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
去除或者添加变量的只读属性 | |
*/ | |
#include <iostream> | |
using namespace std; | |
void makeUpper(const char* c) | |
{ | |
char* c_xxx=const_cast<char*>(c); | |
*c_xxx-=('a'-'A'); | |
} | |
void makeConst(char* c) | |
{ | |
const char* c_xxx=const_cast<const char*>(c); | |
cout<<"makeConst: "<<c_xxx<<endl;; | |
} | |
int main(int argc, char **argv) | |
{ | |
char buffer[]="hello world!"; | |
cout<<"lowerCase="<<buffer<<endl; | |
makeUpper(&buffer[0]); | |
cout<<"upperCase="<<buffer<<endl; | |
makeConst(buffer); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
static_cast是您應該嘗試使用的第一個演員。 它實現類型之間的隱式轉換(如int到float或指向void*指針),它也可以調用顯式轉換函數(或隱式轉換函數)。 在許多情況下,明確說明static_cast不是必需的,但重要的是要注意, T(something)語法等同於(T)something ,應該避免(稍後再說)。 然而, T(something, something_else)是安全的,並且保證調用構造函數。
static_cast也可以通過繼承層次結構進行轉換。 向上(向基類)向上投射是不必要的,但是當向下投射時,只要不通過virtual繼承進行投射就可以使用它。 然而,它不會檢查,而是將層次結構中static_cast行為定義為實際上不是對像類型的類型。
const_cast可用於刪除或添加const到變量; 沒有其他C ++演員能夠刪除它(甚至沒有reinterpret_cast )。 重要的是注意,如果原始變量是const ,則修改以前的const值才是未定義的; 如果使用它來將const引用到沒有使用const聲明的東西,那麼它是安全的。 例如,當基於const成員函數重載時,這可能很有用。 它也可以用於向對象添加const ,例如調用成員函數重載。
const_cast也可以類似於volatile ,儘管不常見。
dynamic_cast幾乎專門用於處理多態。 您可以將任何多態類型的指針或引用轉換為任何其他類類型(多態類型至少有一個虛函數,聲明或繼承)。 您可以使用它不僅僅是向下傾斜 - 您可以側身傾斜,甚至連其他鏈條。 如果可能, dynamic_cast將尋找所需的對象並返回。 如果不能,就會在指針的情況下返回nullptr ,或者在引用的情況下拋出std::bad_cast 。
dynamic_cast有一些局限性。 如果在繼承層次結構中有多個相同類型的對象(所謂的“可怕的鑽石”)並且不使用virtual繼承,則不起作用。 它也只能通過公共繼承 - 它永遠不會通過protected或private繼承。 然而,這很少是一個問題,因為這種繼承形式是罕見的。
reinterpret_cast是最危險的演員,應該非常謹慎地使用。 它將一種類型直接轉換為另一種類型,例如將值從一個指針轉換到另一個指針,或將指針存儲在int或其他各種其他討厭的東西中。 很大程度上,通過reinterpret_cast獲得的唯一保證是,通常如果將結果轉換回原始類型,您將獲得完全相同的值(但如果中間類型小於原始類型,則不會 )。 還有一些reinterpret_cast不能做的轉換。 它主要用於特別奇怪的轉換和位操作,例如將原始數據流轉換為實際數據,或將數據存儲在對齊指針的低位。
原文链接