2009-07-07 59 views
1

如果說使用了強制轉換,結果對象是一個 const對象,這樣說是否正確?在C++中強制生成const對象

...因此只能作爲函數的參數使用,如果 函數接受它作爲const對象?

例如

class C1 { 
    public: C1(int i=7, double d = 2.5){}; 
}; 

void f(C1& c) {}; 

int main(){ 
    f(8); 
    return 1; 
} 
//won't compile 

(當然如果f(....)由值接收參數,則它得到 非const版本它可與工作)

回答

12

一般當特定類型的對象被轉換爲另一種類型的對象(非引用類型)時,會創建一個臨時對象(不是一個const對象)。一個臨時對象(不可見的,無名的,右值)只能綁定(在C++ 98/03中)爲const的引用(除了稱爲「異常對象」的臨時對象)。因此,創建臨時變量的轉換結果只能用作函數的參數,該函數將其作爲const引用接受,或者作爲可以複製/轉換的類型。

因此對於例如

void f(double); // 1 
void f(const int&); // 2 
void f(int&); // 3 

struct B { B(int) { } }; 
struct C { C(int) { } }; 
void f(B b); // 4 
void f(B& b); // 5 
void f(const C& c); //6 
void f(C& c); // 7 

// D inherits from B 
struct D : B { D(int) : B(0) { } }; 
void f(D& d); // 8 

int main() 
{ 
    f((int) 3.0); // calls 2, NOT 3 
    f((float) 3); // calls 1 - const reference requires the same type 
    f(1); // calls 2, NOT 3 

    f((B) 1); // calls 4, not 5 - can accept it by non-const value 
    f((C) 1); // calls 6, not 7 - can accept it by const-reference 

    f((D) 1); // calls 4, not 8 - since a 'D' temporary object can be converted to a 'B' object - but will not bind to a non-const reference 
} 

希望有幫助。

+1

+1:我喜歡這個答案。這可能會有助於給出每次轉換的等級和種類(以顯示爲什麼選擇某個特定版本)。請檢查我是否正確。我列舉了A,B,C,...... - 第一次通話(A):完全匹配到2,轉換爲1.(B)升級到1,轉換爲2.(C)精確匹配到2,轉換爲1.(D)精確匹配到4.(E)精確匹配到6.(F)轉換(派生 - >基礎)到4. - 在所有`const T&`到rvalue`T`的參考綁定中, `const T`被認爲是頂級const,並且不影響rank(`void f(T); void f(const T&); f(T());`ambiguous) – 2009-07-07 17:53:46

0

可以重寫爲:

class C1 
{ 
    public: C1(int i=7, double d = 2.5){}; 

}; 

void f(C1& c){}; 

int main() 
{ 
    C1 c(8); //named 
    f(c); 
    //... can access the modified C1 instance here ... 
    return 1; 
} 

的事情,編譯器不喜歡你的版本是,你C1實例是一個未命名的臨時:這f會修改,但(因爲它是一個未命名的臨時文件)編譯器知道調用者(main)無法接收/保留/注意這些修改。

3

把這個'鑄造'稱爲一點點。你正在做'隱式建構'。隱式構造總是創建一個臨時對象,而這個對象又總是const。

請注意,您可以標記構造函數'explicit',這會阻止您在此處看到的隱式構造調用。但那隻意味着你需要f(C(8))而不是f(8); C實例仍然是const的,因爲它是暫時的,但是請注意沒有正在執行的轉換。

如果您真的需要,另請參閱const_cast瞭解更多的變通辦法。另一個解決方法是做兩個班輪:C c(8); F(C);