explicit 類建構函式的隱式轉換

2021-09-26 04:38:53 字數 1487 閱讀 6668

限制類編譯器呼叫建構函式的隱式轉換(單一入參建構函式)

我們知道c++是乙個型別嚴格的語言,比如下面乙個函式

void test_int_proxy(const int_proxy& v)

呼叫者對其傳參也應該是乙個int_proxy的物件,但是實際情況並非如此。那該如何表述,我個人覺得應該是:編譯器對其傳參應該是乙個int_proxy物件。這兩種表述的區別就是「呼叫者」和「編譯器」的區別。我們來看乙個實際例子,我們先假定int_proxy類這麼定義:

class int_proxy ;

public:

int value() const

private:

int _m;

};該類非常簡單,它有乙個帶引數的建構函式,並使用引數列表形式初始化類的成員變數。

一般情況下我們都會這麼呼叫test_int_proxy方法:

test_int_proxy(int_proxy(100));

這種寫法我想沒人會有異議,但是如果出現下面這種寫法,就可能讓人感覺不可接受了:

test_int_proxy(100);

然而,這種寫法對上述類的定義來說是合法的!其效果和使用int_proxy控制住是一樣的。這是為什麼呢?這便是類建構函式的隱式轉換技術。c++編譯器認為test_int_proxy方法傳入的應該是乙個const型別的int_proxy物件,然而如果它發現引數不是該物件時,就會使用該類中可以使用該引數進行構造物件的方法構造出乙個臨時的物件。我們例子中傳參100是個int型資料,而int_proxy正好有乙個攜帶int引數的建構函式。稍微總結下類建構函式隱式轉換的必要條件:

找不到傳參型別嚴格對應的函式

找到傳參型別嚴格匹配的類的建構函式

因為隱式轉換構造出的是臨時物件,所以不可修改,故觸發隱式轉換的函式的傳參型別必須要使用const修飾

但是個人覺得這種「奇巧淫技」還是不用為好。比如我們**中還有如下函式:

void test_int_proxy(const int& v)

那麼c++編譯器會針對傳100的呼叫上面這個過程。這樣乙個函式呼叫有兩個匹配的呼叫方法就會產生不確定性——這兒指的不確定性並非是指編譯器呼叫哪個方法的不確定性,而是指維護這段**的人對上述**做調整時容易忽略一些問題而導致的「人禍」。

再比如,我們在**中加入下面類和方法

class int_proxy_2 ;

public:

int value() const

private:

int _m;

};void test_int_proxy(const int_proxy_2& v)

那麼編譯器不能確定隱式轉換是要轉換哪個類,更不知道是呼叫哪個test_int_proxy方法了。

限制類建構函式的隱式轉換的方法也很簡單,就是給對應的建構函式加上explict關鍵字

class int_proxy ;

這樣通過隱式轉換而構造臨時物件的圖謀將會被察覺並禁止。

--------------------- 

explicit建構函式之物件的隱式轉換

物件的隱式轉換 對於類型別來說,非同型別的單引數建構函式定義了一條從該引數的型別向該類型別進行隱式轉換的規則。當採用單個實參的初始式時,編譯器會自動根據實參的型別,呼叫單引數建構函式還是複製建構函式。例如,std string 有乙個單引數建構函式 string const char 從而使得可以使...

explicit建構函式

按照預設規定,只有乙個引數的建構函式也定義了乙個隱式轉換,將該建構函式對應資料型別的資料轉換為該類物件,如下面所示 class string string s1 hello ok 隱式轉換,等價於string s1 string hello 但是有的時候可能會不需要這種隱式轉換,如下 class s...

explicit建構函式

在閱讀slicer原始碼時,遇見explicit修飾的建構函式,比較迷惑 explicit qslicerigsreadermodule qobject parent 0 下面就解釋這個問題。按照預設規定,只有乙個引數的建構函式也定義了乙個隱式轉換,將該建構函式對應資料型別的資料轉換為該類物件,如下...