C ++-コンストラクターのオーバーロード-プライベートおよびパブリック
-
22-07-2019 - |
質問
次のコードで次のエラーが表示される理由を教えてください。 call of overloaded" C(int)"あいまいです
C(char x)はプライベートであるため、C(float)ctorのみが外部から見えるようになり、intをfloatに変換することで呼び出す必要があると思います。
しかし、そうではありません。
class C
{
C(char x)
{
}
public:
C(float t)
{
}
};
int main()
{
C p(0);
}
解決
これは" Effective C ++"で説明されています。スコット・マイヤー。これが曖昧な理由は、メンバーの可視性を変更するだけで、他の場所にある既存のコードの意味が変わらないことを保証したかったからです。
それ以外の場合、Cクラスがヘッダーのどこかにあったとします。プライベートC(int)メンバーがある場合、提示するコードはC(float)を呼び出します。何らかの理由でC(int)メンバーが公開された場合、古いコードや呼び出された関数が変更されていなくても、古いコードが突然そのメンバーを呼び出します。
>編集:その他の理由:
さらに悪いことに、次の2つの機能があるとします:
C A::foo()
{
return C(1.0);
}
C B::bar()
{
return C(1.0);
}
これらの2つの関数は、fooまたはbarがCのフレンドとして宣言されているか、AまたはBがそれを継承しているかに応じて、異なる関数を呼び出すことができます。 同一のコードが異なる関数を呼び出すのは怖いです。
(おそらくスコット・マイヤーの議論ほどうまくいっていませんが、それはアイデアです。)
他のヒント
0は int
タイプです。暗黙的にfloatまたはcharに等しくキャストできるため、呼び出しはあいまいです。 これらの目的には可視性は関係ありません。
0.0
、 0。
、または 0.0f
を置くか、 C(char)
コンストラクター全体。
編集:標準の関連部分、セクション13.3:
3)[...]しかし、候補関数と引数リストが特定されると、最適な関数の選択はすべての場合で同じになります。
- 最初に、適切な数の引数を持ち、他の特定の条件を満たす候補関数のサブセットが選択され、実行可能な関数のセットが形成されます(13.3.2)。
- 次に、各引数を各実行可能関数の対応するパラメーターに一致させるために必要な暗黙の変換シーケンス(13.3.3.1)に基づいて、最適な実行可能関数が選択されます。
4)実行可能な最適な関数が存在し、一意である場合、オーバーロード解決は成功し、結果として生成されます。そうしないと、オーバーロードの解決が失敗し、呼び出しの形式が正しくありません。オーバーロードの解決が成功し、使用可能なコンテキストで最適な実行可能関数にアクセスできない場合(11節)、プログラムの形式は正しくありません。
可視性は選択プロセスの一部ではないことに注意してください。
私はそうは思わない:
C p(0);
に変換されています:
C(float t)
おそらくする必要がある:
C p(0.0f);