int main() {
int theInt = 5;
/**
* Constructor "Example(int val)" in effect at the statement below.
* Same as "Example exObject(theInt);" or "Example exObject = Example(theInt);"
*/
Example exObject = theInt; // 1
Example ctr(5);
/**
* "operator unsigned int()" in effect at the statement below.
* What gets assigned is the value returned by "operator unsigned int()".
*/
int theInt1 = ctr; // 2
return 0;
}
ステートメント 1 で、コンストラクターExample(int val)
が呼び出されます。として宣言するとexplicit Example(int val)
、コンパイル時エラーが発生します。つまり、このコンストラクターに対して暗黙的な変換は許可されません。
割り当てられた値がそれぞれの引数の型である場合、すべての単一引数コンストラクターは暗黙的に呼び出されます。単一引数コンストラクターの前にキーワードを使用するexplicit
と、暗黙的なコンストラクターの呼び出しが無効になり、暗黙的な変換が無効になります。
コンストラクターが明示的に宣言されている場合、つまりexplicit Example(int val)
、各ステートメントに対して次のことが起こります。
Example exObject(theInt); // Compile time error.
Example exObject = theInt; // Compile time error.
Example exObject(Example(theInt)); // Okay!
Example exObject = Example(theInt); // Okay!
また、暗黙的なコンストラクター呼び出し、つまり暗黙的な変換の場合、割り当てられた値は右辺値、つまり左辺値 (theInt) を使用して暗黙的に作成された名前のないオブジェクトであることに注意してください。これは、暗黙的な変換の場合、コンパイラーが変換することを示しています。
Example exObject = theInt;
に
Example exObject = Example(theInt);
そのため、(C++11 では) 左辺値、つまりtheInt
割り当てに名前付きの値を使用していることを確認して、左辺値コンストラクターが呼び出されることを期待しないでください。割り当てられた値は実際には左辺値を使用して作成された名前のないオブジェクトであるため、呼び出されるのは右辺値コンストラクターです。ただし、これは、コンストラクターの左辺値バージョンと右辺値バージョンの両方がある場合に適用されます。
at ステートメント 2operator unsigned int()
が呼び出されます。奇妙な名前の通常の関数呼び出しと、暗黙的な変換が発生したときに自動的に呼び出される可能性があるという事実と単純に考えてください。その関数によって返される値は、式で割り当てられた値です。また、実装では返される値は int であるため、正しく割り当てられint theInt1
ます。
正確には、キャスト演算子である演算子をoperator unsigned int()
オーバーロードします。()
あなたの場合、それはオーバーロードされているint
ため、クラスのオブジェクトが暗黙的な型キャストにExample
割り当てられるたびに、 toからのキャストが行われ、呼び出されます。したがって、int
Example
int
operator unsigned int()
int theInt1 = ctr;
と同等です
int theInt1 = (int)ctr;