2.11 C++轉型構造函數
參考:http://www.weixueyuan.net/view/6343.html
總結:
帶參數的構造函數中有兩種比較常見的構造函數:拷貝構造函數和轉型構造函數。
轉型構造函數只有一個參數,如果該參數是int型,則我們是將int型對象轉換為類對象。
直接強制關閉掉這種隱式類型轉換,在C++中,通過關鍵字explicit可以實現該功能。
在C++中, 如果的構造函數只有一個參數時, 那麽在編譯的時候就會有一個缺省的轉換操作:將該構造函數對應數據類型的數據轉換為該類對象。
C++中的explicit關鍵字只能用於修飾只有一個參數的類構造函數, 它的作用是表明該構造函數是顯示的, 而非隱式的, 跟它相對應的另一個關鍵字是implicit, 意思是隱藏的,類構造函數默認情況下即聲明為implicit(隱式).
explicit關鍵字只對有一個參數的類構造函數有效, 如果類構造函數參數大於或等於兩個時, 是不會產生隱式轉換的, 所以explicit關鍵字也就無效了.
但是, 也有一個例外, 就是當除了第一個參數以外的其他參數都有默認值的時候, explicit關鍵字依然有效, 此時, 當調用構造函數時只傳入一個參數, 等效於只有一個參數的類構造函數。
在前面,我們已經將構造函數劃分為兩類:默認構造函數(不帶參數的構造函數)和帶參構造函數。其中帶參數的構造函數中有兩種比較常見的構造函數:拷貝構造函數和轉型構造函數。我們先來了解一下轉型構造函數。
轉型構造函數用於類型間的轉換,將其它數據類型轉變為類的對象類型。轉型構造函數只有一個參數,如果該參數是int型,則我們是將int型對象轉換為類對象,如果該參數類型為char *類型,我們則是將字符串常量轉換為類對象。
例1:
- class Age
- {
- public:
- Age(int a){age = a;}
- private :
- int age;
- }
在本例中Age(int a)即為一個轉型構造函數,該構造函數僅有一個參數,該構造函數是將int型轉換為類對象類型的。
例2:
- class student
- {
- public:
- student(){}
- student(char * n){name = n;}
- private :
- char * name;
- }
在本例中,student類中有兩個構造函數,一個是默認構造函數,另一個是轉型構造函數,該構造函數將字符串常量轉換為類對象類型。
假設我們在程序設計過程中有一個以類對象作為函數參數的函數,函數聲明如下:
- void fun(student s); //函數聲明
如果我們設計了如下程序以調用該函數:
- char * name = “Harry Potter”;
- fun(name);
在例2中我們恰好在student類中定義了這樣一個轉型構造函數student(char * n);,該函數可以將字符串常量轉換為student類的對象。在我們運行fun(name);語句時,編譯器會自動調用轉型構造函數將name轉換為student類的對象,然後調用void fun(student s);函數。這一系列的過程都是編譯器自動完成的,我們稱此時的student類的轉型構造函數student(char * n);支持隱式類型轉換。之所以說是隱式的,是因為這個轉型過程完全由編譯器完成,無需程序設計人員顯示轉換類型。
隱式類型轉換給程序設計人員帶來了一定的便利,但是隱式類型轉換可能會給我們設計的程序帶來一些難以覺察的細微錯誤。有時候我們為了避免這種錯誤,我們希望直接強制關閉掉這種隱式類型轉換,在C++中,通過關鍵字explicit可以實現該功能。
例3:
- class student
- {
- public:
- student(){}
- explicit student(char * n){name = n;}
- private :
- char * name;
- }
如例3所示,我們在轉型構造函數前加上了explicit關鍵字,如此一來,我們再想通過以下語句:
- char * name = “Harry Potter”;
- fun(name);
調用void fun(student s);函數則是無法通過編譯的,因為fun函數的參數是student類的對象而非字符串常量,並且student類的轉型構造函數被標記為explicit,因此無法隱式地將字符串常量轉換為student 類對象。使用explicit關鍵字的好處就在於將難以察覺的後期運行時可能會出現的錯誤提前到了編譯期,如此一來改正錯誤就比較容易了。
2.11 C++轉型構造函數