2009-07-07 11 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 

答えて

12

(F(...)は値によって引数を受信した場合はもちろん、それはそれで動作することができる非constバージョン を取得)通常ときに、特定のタイプのオブジェクト別の型のオブジェクト(非参照型)に変換されると、一時オブジェクトが作成されます(constオブジェクトではありません)。一時オブジェクト(invisible、nameless、rvalue)は、(例外オブジェクトとして知られている一時的なものを除いて)constである参照にのみ(C++ 98/03で)バインドできます。したがって、一時的なものを生成する変換の結果は、それを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):2への完全一致、1への変換、(B)1への昇格、2への変換、(C)2への完全一致、 'const T'の値が 'T'になるすべての参照バインディングでは、(T)は、 (const T); f(T()); 'ambiguous) –

+0

はい、あなたはそうだと思います。私たちはここでORを扱っているので、http://stackoverflow.com/questions/1092714/conversion-precedence-in-c/1092724#1092724、私はあまりにも集中したくないオーバーロードの解決 - 一時的なバインドの可能性について - おそらく私は別の関数名を使用して、それをよりシンプルに保つべきでしょうか? –

+0

ああそうだ。私は何が良いかわからない。しかし、私はそれが現在どのようにそれが好きです。人々はあなたの他の答えを読んで、特にいくつかのバージョンが特に好まれる理由を知りたい場合は、コメントセクションを調べることができます。 –

0

あなたはようことを書き換えることができます:それはだから(fが変更されますが、:

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インスタンスが非命名一時的なものであるということですコンパイラは、呼び出し元(main)がこれらの変更を受信/保存/通知する方法がないことをコンパイラが認識しています。

3

これを「キャスティング」と呼ぶのは少しです。あなたは「暗黙の構築」を行っています。暗黙の構成では常に一時オブジェクトが作成されます。一時オブジェクトは常にconstです。

コンストラクタを '明示的に'マークすることができます。これは、ここに表示されている暗黙的な建設呼び出しをブロックすることに注意してください。しかし、これはf(8)の代わりにf(C(8))が必要であることを意味します。 Cインスタンスは一時的なのでconstのままですが、キャストは実行されていないことに注意してください。

本当に本当に必要な場合は、汚れた回避策についてはconst_castも参照してください。他の回避策は2つのライナーを行うことです:C c(8); f(c);