2013-02-25 60 views
34

我聽說C++有一些叫做「轉換構造函數」或「轉換構造函數」的東西。這些是什麼,它們的用途是什麼?我看到它關於這個代碼中提到:什麼是C++中的轉換構造函數?它是爲了什麼?

class MyClass 
{ 
    public: 
    int a, b; 
    MyClass(int i) {} 
} 

int main() 
{ 
    MyClass M = 1 ; 
} 
+3

@MooingDuck:我理解的意圖,但用戶至少應該花時間來正確地制定*問題*。 – 2013-02-25 22:41:30

+13

我真的不明白這個問題有什麼問題 - 這是一個問題,即什麼是轉換構造函數,它們是什麼。顯然他問了這個問題,因爲他沒有完全理解他們的用法。 我正在學習C++,每當我看到一個新的概念時,我都會將它搜索到,這就是我如何解決這個問題。很多時候我都會用StackOverFlow來解決這個問題,這有助於我理解這個概念。我認爲這應該被StackOverFlowers鼓勵。 – dan12345 2014-06-26 07:24:37

+6

瘋了。我有同樣的非真實問題。猜猜這是一個完整的問題。 – bvj 2014-08-21 18:12:53

回答

39

轉換構造函數的定義在C++ 03和C++ 11之間是不同的。在這兩種情況下,它都必須是非構造函數(否則它不會涉及隱式轉換),但對於C++ 03,它也必須可以用一個參數調用。那就是:

struct foo 
{ 
    foo(int x);    // 1 
    foo(char* s, int x = 0); // 2 
    foo(float f, int x);  // 3 
    explicit foo(char x); // 4 
}; 

構造1和2是在C++ 03和C++ 11都轉換構造。構造函數3必須帶有兩個參數,它只是C++ 11中的一個轉換構造函數。最後一個構造函數4不是一個轉換構造函數,因爲它是explicit

  • C++ 03:§12.3。1

    構造函數聲明沒有功能說明符explicit可以用一個單一的參數被稱爲指定從其第一參數與其類的類型的類型轉換。這樣的構造函數被稱爲轉換構造函數。

  • C++ 11:§12.3.1

    而不功能說明符explicit聲明的構造函數指定到其類的類型從類型及其參數的轉換。這樣的構造函數被稱爲轉換構造函數。

爲什麼具有比認爲是轉換構造在C++ 11的單個參數多個構造?這是因爲新標準爲我們提供了一些方便的語法來使用支持初始化列表來傳遞參數和返回值。請看下面的例子:

foo bar(foo f) 
{ 
    return {1.0f, 5}; 
} 

指定返回值作爲支撐,初始化列表被認爲是一個轉換的能力。這使用foo的轉換構造函數,其採用floatint。另外,我們可以通過做bar({2.5f, 10})來調用這個函數。這也是一個轉換。由於它們是轉換,因此它們用於構造函數轉換構造函數是有意義的。

重要的是要注意的,因此,這使得foo的構造,這需要floatintexplicit函數說明將從停止編譯上面的代碼是很重要的。只有存在可用於執行作業的轉換構造函數時,才能使用上述新語法。

  • C++ 11:§6.6.3:

    return語句與支撐-INIT列表初始化對象或參考從功能通過複製被返回-list-initialization(8.5.4)從指定的初始化程序列表中。

    第8.5節:

    時發生的初始化[...]在參數傳遞[...]被稱爲拷貝初始化。

    §12.3.1:

    一個明確的構造函數構造對象一樣,不明確的構造函數,但這樣做只會在直接初始化語法(8.5)或在鑄件(5.2.9, 5.4)被明確使用。

11

與轉換構造隱含轉換

讓我們在這個問題更加複雜

class MyClass 
{ 
    public: 
    int a, b; 
    MyClass(int i) {} 
    MyClass(const char* n, int k = 0) {} 
    MyClass(MyClass& obj) {} 
} 

前兩個構造函數轉換構造函數的例子。第三個是複製構造函數,因此它是另一個轉換構造函數。

轉換構造函數啓用從參數類型到構造函數類型的隱式轉換。這裏,第一個構造函數可以將int轉換爲MyClass類的對象。第二個構造函數可以將字符串轉換爲類MyClass的對象。第三...從類MyClass的對象到類MyClass的對象!

要成爲一個轉換構造函數,構造函數必須具有單個參數(在第二個參數中,第二個參數具有一個默認值),並聲明爲不帶關鍵字explicit

然後,初始化主可以是這樣的:

int main() 
{ 
    MyClass M = 1 ; 
    // which is an alternative to 
    MyClass M = MyClass(1) ; 

    MyClass M = "super" ; 
    // which is an alternative to 
    MyClass M = MyClass("super", 0) ; 
    // or 
    MyClass M = MyClass("super") ; 
} 

明確的關鍵字和構造

現在,如果我們使用了explicit關鍵詞是什麼?

class MyClass 
{ 
    public: 
    int a, b; 
    explicit MyClass(int i) {} 
} 

然後,編譯器不會接受

int main() 
    { 
     MyClass M = 1 ; 
    } 

,因爲這是隱式轉換。相反,必須寫

int main() 
    { 
     MyClass M(1) ; 
     MyClass M = MyClass(1) ; 
     MyClass* M = new MyClass(1) ; 
     MyClass M = (MyClass)1; 
     MyClass M = static_cast<MyClass>(1); 
    } 

explicit關鍵字總是被用來防止隱式轉換爲一個構造函數和它應用於構造類聲明。

+0

第一個示例中的第三個構造函數不是複製構造函數。複製構造函數參數必須是'X&','const X&',volatile X&'或'const volatile X&'之一。 – 2013-02-25 22:15:35

+0

你可以在最後一個例子中寫'MyClass M(1)'等。小心那些多字符文字。 – chris 2013-02-25 22:16:10

+0

你發佈之前是否編寫過代碼?您的*字符串*實際上是多字符常量,並且不會隱式轉換爲'char const *'! – Praetorian 2013-02-25 22:18:29

相關問題