explicit 類構造函數的隱式轉換

原文鏈接:https://blog.csdn.net/breaksoftware/article/details/54894444

限制類編譯器調用構造函數的隱式轉換(單一入參構造函數)

 我們知道C++是一個類型嚴格的語言,比如下面一個函數

void test_int_proxy(const int_proxy& v) {
    printf("%d", v.value());
}
        調用者對其傳參也應該是一個int_proxy的對象,但是實際情況並非如此。那該如何表述,我個人覺得應該是:編譯器對其傳參應該是一個int_proxy對象。這兩種表述的區別就是“調用者”和“編譯器”的區別。我們來看一個實際例子,我們先假定int_proxy類這麼定義:

class int_proxy {
public:
    int_proxy(int n) : _m(n) {};
public:
    int value() const {
        return _m;
    }
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) {
    printf("%d", v + 100);
}
        那麼C++編譯器會針對傳100的調用上面這個過程。這樣一個函數調用有兩個匹配的調用方法就會產生不確定性——這兒指的不確定性並非是指編譯器調用哪個方法的不確定性,而是指維護這段代碼的人對上述代碼做調整時容易忽略一些問題而導致的“人禍”。

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

class int_proxy_2 {
public:
    int_proxy_2(int n) : _m(n) {};
public:
    int value() const {
        return _m + 100;
    }
private:
    int _m;
};
 
void test_int_proxy(const int_proxy_2& v) {
    printf("%d", v.value());
}
        那麼編譯器不能確定隱式轉換是要轉換哪個類,更不知道是調用哪個test_int_proxy方法了。

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

class int_proxy {
public:
    explicit int_proxy(int n) : _m(n) {};
        這樣通過隱式轉換而構造臨時對象的圖謀將會被察覺並禁止。
--------------------- 
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章