1. 隱式和顯式初始化
1.1 C++隱式初始化
int ival(1024);
string hello("Hello world.")
1.2 C++顯式初始化
int ival = 1024;
string hello = "Hello world."
*PS: 注意這裡"=" 文法是拷貝建構函式而不是賦值運算!
因為一個新對象被定義一定要有一個建構函式而不不是一個賦值操作
string hello;
hello = "Hello world"; <- 這裡hello 已經被定義了,才是賦值操作.
2.隱式和顯式類型轉換.
2.1
C++隱式轉換髮生在四種情況下
* 在混合類型的算術運算式中
int ival = 3;
double dval = 3.1415
ival + dval; //ival 被提升為double 類型:3.0
* 用一種類型的運算式賦值
int *pi = NULL; // NULL(0)被轉換成了int* 類型的null 指標值
* 用一個運算式傳遞給一個函數調用
extern double sqrt(double);
sqrt(2); //2被提升為double類型: 2.0
* 從一個函數返回一個運算式
double difference(int ival1, int ival2)
{
return ival1 - ival2; //傳回值被提升為double 類型.
}
2.2
C++內建類型(char,int,short,double etc.)對像之間預設含有隱式轉換
2.3
C++使用者定義類對象之間可以含有隱式轉換.
void dosomething(A aObject);
class A {
public:
A(int x = 0);
}
dosomething(20); // Ok 隱式轉換
2.4
C++顯式轉換包含四種轉換
static_cast : 編譯期的轉化,不能轉換掉exdivssion的const、volitale、或者__unaligned屬性
*所有內建類型對象之間的隱式轉換都可用static_cast.
*把null 指標轉換成目標類型的null 指標用static_cast。
*把任何類型的運算式轉換成void類型用static_cast。
*類層次間的上行轉換和下行轉換也可以用static_cast,但下行轉換即當把基類指標或引用轉換成子類表示時,由於沒有動態類型檢查,所以是不安全的.反之是安全的.
dynamic_cast : 運行期的轉換,類層次間的上行轉換和下行轉換
* dynamic_cast具有類型檢查的功能,下行轉換的效果跟static_cast是一樣的,但下行轉換比static_cast更安全。
* dynamic_cast還支援交叉轉換,兩個類如果有共同的祖先,他們的指標就可以用dynamic_cast.
const_cast : 編譯期的轉化,類型中的常量
reinterpret_cast : 任何指標都可以轉換成其它類型的指標,可用於如char* 到 int*,或者One_class* 到 Unrelated_class* 等的轉換,因此可能是不安全的。
2.5
C++內建類型指標之間不含有隱式轉換(void * 除外),需要顯式轉換。
int ival = 0;
char* pc = NULL;
int* pi = NULL;
void* pv = NULL;
const char* pcc = "Hello world";
const int* pci = &ival;
const void* pcv = NULL;
pc = pi; //錯誤,沒有標準的隱式轉換.
pc = reinterpret_cast<char*>(pi); //必須使用reinterpret_cast 在位元模式層次的顯式轉換
pc = pv; //錯誤,沒有標準的隱式轉換.
pc = static_cast<char*>(pv); //static_cast顯式轉換
pc = pcc; //錯誤,沒有標準的隱式轉換.
pc = const_cast<char*>(pcc); //const_cast顯式轉換
pc = pcv; //錯誤,沒有標準的隱式轉換.
pc = static_cast<char*>(const_cast<void*>(pcv)); //先const_cast 後 static_cast.
pv = pc; // OK; 隱式轉換到void*
pv = pi; // OK; 隱式轉換到void*
pv = pcc; //錯誤,沒有標準的隱式轉換.
pv = const_cast<char*>(pcc); //OK, const_cast顯式轉換,並且char* 隱式轉換到void*
pv = pcv;//錯誤,沒有標準的隱式轉換.
pv = const_cast<void*>pcv;//OK, const_cast顯式轉換.
pcc = pc; // OK; 隱式轉換到const char*
pcc = pi; // 錯誤,沒有標準的隱式轉換.
pcc = reinterpret_cast<char*>(pi); //必須使用reinterpret_cast 在位元模式層次的顯式轉換.
pcc = pv; // 錯誤,沒有標準的隱式轉換.
pcc = static_cast<char*>(pv); //static_cast顯式轉換
pcc = pci;// 錯誤,沒有標準的隱式轉換.
pcc = reinterpret_cast<char*>pci; //必須使用reinterpret_cast 在位元模式層次的顯式轉換.
pcc = pcv;//錯誤,沒有標準的隱式轉換.
pcc = static_cast<const char*>(pcv); //static_cast顯式轉換.
pcv = pv; // OK; 隱式轉換到const void*
pcv = pc; // OK; 隱式轉換到const void*
pcv = pi; // OK; 隱式轉換到const void*
pcv = pcc;// OK; 隱式轉換到const void*
2.6
顯式轉換可以消除不必要的提升.
double dval;
int ival;
ival += dval;
這段賦值,首先將ival提升到double型,然後與dval相加,得到結果再截取成int.
通過顯式轉換,消除ival 從int型到double型的不必要提升.
ival += static_cast<int>(dval);
2.7
C++使用者定義對象之間可以禁止隱式轉換。
void dosomething(A aObject);
class A {
public:
explicit A(int x = 0);
}
dosomething(20); // ERROR 隱式轉換被禁止.
dosomething(static_cast<A>(20)); // OK 顯式轉換.
被聲明為explicit 的建構函式通常比non-explicit更好.
2.8
綜合起來說C++ 中應該盡量不使用轉換,盡量使用顯式轉換來代替隱式轉換.
盡量不用reinterper_cast 顯式轉換.