型別轉化函式和單引數建構函式

2022-04-03 05:45:54 字數 2670 閱讀 9038

c++編譯器被人如此詬病的主要原因就是c++揹著使用者幹了太多的事情,而這些事情往往容易產生語義困惑(知道為什麼溺愛孩子,給孩子一切都安排好,反而會受到不肖子的臭罵了吧??)

c++隱含做的事情很多,下面我就單從型別轉化這個主題大概說一下c++都在型別轉化過程中做了什麼。不當之處請多批評指正:

1、將乙個類轉化成為其他型別:

類的作者可以定義該類的物件向指定資料型別的轉換函式,具體使用方法是在類中定義

operator typename(),注意這樣的型別轉化函式雖然沒有標明返回值,但是必須返回轉化目標型別的

物件。函式不能有形參列表。

比如:

class

string

char*_str;

}

當需要將string轉化成為char*的時候,比如 string[0]=『a』;編譯器就會嘗試把string向支援下標操作的型別轉化,看到有

乙個char*型別支援下標操作,那麼就根據使用者定義的型別轉化函式將其轉化成為char* 相當於是_str[0]='a'

如果發現有多個轉化函式都支援下標操作,那麼編譯不會通過。(同理也可以定義operator bool(),然後在

if(...)語句中呼叫這個向bool型別轉化的函式)

2、將乙個其他型別轉化為本型別

相當於是operator type的逆操作,本質上是由乙個其他型別來構造本型別,其實現方式也是使用帶乙個其他型別作為形參的建構函式來做這個轉化,比如:

class

string

//如果下面一行是:explicit string(char* ch),那麼就不能通過傳值來呼叫建構函式

string(char*ch)

~string(){}

char*_string;

};

這樣就可以把乙個char* 直接通過呼叫string的建構函式來構造成為string(這個建構函式會在函式傳值過程中構造區域性物件)。

下面通過乙個統一的例子來說明這兩種轉化:

#include #include 

class

string

//如果下面一行是:explicit string(char* ch),那麼就不能通過傳值來呼叫建構函式

string(char*ch)

~string(){}

string(string&str){}

operator

char*()

operator

int()

char*_string;

};void

print(string ch)

intmain()

分析一下上面這個例子:

1、string str("abcde") 首先使用string的帶引數的建構函式初始化了string::_string

2、str[1]=『z』 編譯器檢測到這裡需要將string型別轉化為char*型別才能呼叫下標操作符,於是呼叫operator char*()

3、int a=str 同理,編譯器檢測到需要將string轉化為int,於是呼叫operator int()

4、print(str._string) 注意這裡呼叫的是void print(string ch),需要的引數是乙個string物件(值傳遞),而傳入的引數str._string是乙個char*,這個時候編譯器會查詢到帶引數的建構函式string(char*),呼叫這個建構函式把char*轉化為乙個string物件傳遞給print函式列印。

5、進入print函式以後,呼叫printf函式,這個函式需要乙個char*指標,於是又把string轉化為了char*,又呼叫了operator char*()

輸出:

在第一步呼叫constructor,第二步呼叫operator char*(),第三步呼叫operator int(),

第四步:在給print傳值的過程中由char*生成string的臨時物件,又呼叫了constructor

第五步:進入printf後,又把臨時的string物件轉化成了char*,最後輸出

總結:1、把乙個類的物件隱式的轉化成為另乙個類的物件,通過定義轉化函式進行處理

2、通過乙個類的物件構造另乙個類的物件,呼叫對應單引數的建構函式

注:拷貝建構函式其實也是建構函式的一種(也會通過函式傳值、函式返回、顯示呼叫三種方式呼叫),只是通過另乙個相同類的物件轉化成為新物件而已。

c++智慧型指標問題:

智慧型指標維護了物件的引用次數,如果引用次數等於0,那麼就釋放這片記憶體,每次這個物件被賦值為其他物件,都會增加引用次數,每次呼叫析構函式就會減少一次引用次數。

傳值問題:一般智慧型指標在實現的時候都會支援乙個單引數(智慧型指標指向物件的指標)的建構函式,用普通的指標構造智慧型指標。這就遇到乙個問題,當把乙個普通指標傳遞給乙個需要傳入智慧型指標的函式時,會隱式呼叫智慧型指標的建構函式,初始化引用為1,但這個智慧型指標是乙個區域性變數,當函式結束的時候,智慧型指標發現引用從1變成了0,就會自動釋放這片記憶體。這也許是程式設計師不想要的。辦法是在智慧型指標的這個單引數建構函式前寫上explicit,防止這種錯誤的發生,但share_ptrsp= new type();這樣的語法又不能用了,必須寫成:share_ptrsp= share_ptr(new type());又帶來了麻煩,所以還是權衡一下吧,想要圖方便,就會有風險.....

關於單參建構函式和型別轉換函式

其實單參建構函式就是只有乙個引數的建構函式,拷貝建構函式就是他的一種,單參建構函式和型別轉化函式用法正好相反,單參建構函式是把形參中的值或者是物件轉化為本物件,而型別轉化函式是把本物件轉換為乙個值或者乙個其他物件 如下 itoa是乙個可以把int型資料轉化為string型資料的函式。在 includ...

C 單引數建構函式 小結

單引數建構函式是一種比較特殊的建構函式 例如 calss catype public catype int a 單一引數建構函式 nmember a private int nmember void main a cainstance 2 此處會呼叫單一引數建構函式,而不會呼叫賦值運算子,切記 這種...

預設引數的建構函式和拷貝建構函式

看到網路上面一句描述 在乙個類中定義了全部是預設引數的建構函式的後,不能再定義過載建構函式 感覺會有歧義,其實看怎麼理解了。應該還是可以定義拷貝建構函式或更多引數的建構函式的,只要在建構函式的選擇上不會有二義性就可以 如下 include class test int getj int getp t...