C 中顯式和隱式初始化和型別轉換

2021-05-28 14:39:06 字數 4453 閱讀 6045

有乙個類的建構函式為: a(int i) : m_i(i){}

1.1 c++顯式初始化

內建型別:

int ival = 1024;

string hello = "hello world."

自定義型別的顯式初始化:

a abc(200);//顯式初始化,直接呼叫建構函式

a a = a(1);//直接呼叫建構函式,沒有臨時物件,作用域結束時析構

a* e = new a(2);//直接呼叫建構函式,使用delete時析構

a d(*e);//顯式初始化,呼叫拷貝建構函式,作用域結束時析構

1.2 c++隱式初始化

內建型別:

int ival(1024);

string hello("hello world.")

自定義型別的隱式初始化:

a c = 0;//這是一種隱式初始化,直接呼叫建構函式,沒有臨時物件。不要看到=號就以為要用拷貝建構函式。

a b = a;//用乙個物件隱式初始化另一物件,呼叫拷貝建構函式,作用域結束時析構

1.3 賦值操作符:

對已初始化了的物件賦值,用賦值操作符。如果是宣告的同時為物件賦值,則呼叫建構函式或者拷貝建構函式。

a a(1); //顯式初始化

a = 10; // 呼叫建構函式構造一臨時物件,呼叫賦值函式,賦值後臨時物件馬上被析構

2.1 隱式型別轉換

2.1.1 c++隱式轉換發生在四種情況下:(混合運算,賦值,傳參,返回值)

1)在混合型別的算術表示式中

int ival = 3;

double dval = 3.1415

ival + dval; //ival 被提公升為double 型別:3.0

2)用一種型別的表示式賦值

int *pi = null; // null(0)被轉換成了int* 型別的空指標值

3)用乙個表示式傳遞給乙個函式呼叫

extern double sqrt(double);

sqrt(2); //2被提公升為double型別: 2.0

4)從乙個函式返回乙個表示式

double difference(int ival1, int ival2)

2.1.2內建型別對像之間預設隱式轉換

c++內建型別(char,int,short,double etc.)對像之間預設含有隱式轉換

2.1.3使用者定義類物件之間可以含有隱式轉換

c++使用者定義類物件之間可以含有隱式轉換.

void dosomething(a aobject);

class a

dosomething(20); // ok 隱式轉換,如用explicit修飾建構函式,則不能隱式轉換

2.2 顯式型別轉換

c++顯式轉換包含四種轉換

static_cast :編譯期的轉化,不能轉換掉表示式的const、volitale、或者

__unaligned屬性

*所有內建型別物件之間的隱式轉換都可用static_cast.

*把空指標轉換成目標型別的空指標用static_cast。

*把任何型別的表示式轉換成void型別用static_cast。

*類層次間的上行轉換和下行轉換也可以用static_cast,但下行轉換即當把基類指標或引用轉換成子類表示時,由於沒有動態型別檢查,所以是不安全的.反之是安全的.

dynamic_cast :執行期的轉換,類層次間的上行轉換和下行轉換

* dynamic_cast具有型別檢查的功能,上行轉換的效果跟static_cast是一樣的,但下行轉換比static_cast更安全。

*dynamic_cast還支援交叉轉換,兩個類如果有共同的祖先,他們的指標就可以用dynamic_cast.

const_cast

:編譯期的轉化,型別中的常量,該運算子用來修改型別的const或volatile屬性。

一、常量指標被轉化成非常量指標,並且仍然指向原來的物件;

二、常量引用被轉換成非常量引用,並且仍然指向原來的物件;

三、常量物件被轉換成非常量物件。

reinterpret_cast :任何指標都可以轉換成其它型別的指標,可用於如char* 到 int*,或者one_class* 到 unrelated_class* 等的轉換,因此可能是不安全的。

2.3內建型別指標之間不含有隱式轉換(void * 除外)

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(pi); //必須使用reinterpret_cast 在位模式層次的顯式轉換

pc = pv; //錯誤,沒有標準的隱式轉換.

pc = static_cast(pv); //static_cast顯式轉換

pc = pcc; //錯誤,沒有標準的隱式轉換.

pc = const_cast(pcc); //const_cast顯式轉換

pc = pcv; //錯誤,沒有標準的隱式轉換.

pc = static_cast(const_cast(pcv)); //先const_cast 後 static_cast.

pv = pc; // ok; 隱式轉換到void*

pv = pi; // ok; 隱式轉換到void*

pv = pcc; //錯誤,沒有標準的隱式轉換.

pv = const_cast(pcc); //ok, const_cast顯式轉換,並且char* 隱式轉換到void*

pv = pcv;//錯誤,沒有標準的隱式轉換.

pv = const_castpcv;//ok, const_cast顯式轉換.

pcc = pc; // ok; 隱式轉換到const char*

pcc = pi; // 錯誤,沒有標準的隱式轉換.

pcc = reinterpret_cast(pi); //必須使用reinterpret_cast 在位模式層次的顯式轉換.

pcc = pv; // 錯誤,沒有標準的隱式轉換.

pcc = static_cast(pv); //static_cast顯式轉換

pcc = pci;// 錯誤,沒有標準的隱式轉換.

pcc = reinterpret_castpci; //必須使用reinterpret_cast 在位模式層次的顯式轉換.

pcc = pcv;//錯誤,沒有標準的隱式轉換.

pcc = static_cast(pcv); //static_cast顯式轉換.

pcv = pv; // ok; 隱式轉換到const void*

pcv = pc; // ok; 隱式轉換到const void*

pcv = pi; // ok; 隱式轉換到const void*

pcv = pcc;// ok; 隱式轉換到const void*

2.4顯式轉換可以消除不必要的提公升

double dval;

int ival;

ival += dval;

這段賦值,首先將ival提公升到double型,然後與dval相加,得到結果再擷取成int.

通過顯式轉換,消除ival 從int型到double型的不必要提公升.

ival += static_cast(dval);

2.5c++使用者定義物件之間可以禁止隱式轉換

void dosomething(a aobject);

class a

dosomething(20); // error 隱式轉換被禁止.

dosomething(static_cast(20)); // ok 顯式轉換.

被宣告為explicit 的建構函式通常比non-explicit更好,只有乙個引數的建構函式才宣告為explicit.

2.6總結

綜合起來說c++ 中應該盡量不使用轉換,盡量使用顯式轉換來代替隱式轉換.

盡量不用reinterper_cast 顯式轉換.

C 隱式和顯式 初始化,型別轉換

1.隱式和顯式初始化 1.1 c 隱式初始化 int ival 1024 string hello hello world.1.2 c 顯式初始化 int ival 1024 string hello hello world.ps 注意這裡 語法是拷貝建構函式而不是賦值運算 因為乙個新物件被定義一定...

顯式 隱式型別轉換 初始化

隱式和顯式初始化 a c 隱式初始化 int ival 1024 string hello hello rookie b c 顯式初始化 int val 1024 string hello hello rookie 這裡的 語法是拷貝建構函式,而不是賦值運算。因為乙個新物件被定義一定要有乙個建構函式...

顯式型別轉換和隱式型別轉換

typeof六種資料型別 number string boolean undefined object function var num 123 console.log typeof num number var num1 true console.log typeof num1 string va...