10

編集:Mike Seymour のコメントに従って、それに応じて実装を置き換えoperator std::string () const;て変更しました。operator char * () const;これにより暗黙のキャストが可能になりますが、何らかの理由で、unsigned long int 演算子が char * 演算子よりも優先されます。クラス、std::string がある場合。私の CustomizedInt クラスは、私が望む機能をサポートするためにいくつかのものから継承する必要があるという予感があります。に関するマイクのコメントを詳しく説明してもらえstd::basic_stringますか? 私はそれを正しく理解したかどうかわかりません。


私はこのコードを持っています:

#include <string>
#include <sstream>
#include <iostream>

class CustomizedInt
{
private:
    int data;
public:
    CustomizedInt() : data(123)
    {
    }
    operator unsigned long int () const;
    operator std::string () const;
};

CustomizedInt::operator unsigned long int () const
{
    std::cout << "Called operator unsigned long int; ";
    unsigned long int output;
    output = (unsigned long int)data;
    return output;
}

CustomizedInt::operator std::string () const
{
    std::cout << "Called operator std::string; ";
    std::stringstream ss;
    ss << this->data;
    return ss.str();
}

int main()
{
    CustomizedInt x;
    std::cout << x << std::endl;
    return 0;
}

「Called operator unsigned long int; 123」を出力します。私の質問は次のとおりです。

  1. 演算子 unsigned long int を削除した後、x を明示的に std::string にキャストする必要があるのはなぜですか? 暗黙のキャスト演算子 (std::string) を直接呼び出さないのはなぜですか?
  2. どの暗黙的なキャストが許可され、どの優先順位が優先されるかを説明するドキュメントはありますか? 演算子 unsigned int を演算子 unsigned long int と共にこのクラスに追加すると、 << 演算子のあいまいさに関するコンパイラ エラーが発生するようです...
  3. また、そのような演算子を定義するのは適切ではないことはわかっていますが、関連する注意事項を完全に理解しているかどうかはわかりません。誰かそれらの概要を教えてください。パブリック メソッドの ToUnsignedLongInt と ToString を定義する方がよいのでしょうか。
4

1 に答える 1

8

演算子 unsigned long int を削除した後、x を明示的に std::string にキャストする必要があるのはなぜですか? 暗黙のキャスト演算子 (std::string) を直接呼び出さないのはなぜですか?

文字列用のバージョンはテンプレートであり、テンプレート<<のパラメーターによってパラメーター化されますstd::basic_string(std::stringそれ自体がそのテンプレートの特殊化です)。これは、引数に依存するルックアップによってのみ選択できます。これは、引数が実際に の特殊化でありstd::basic_string、変換可能なものではない場合にのみ機能します。

どの暗黙的なキャストが許可され、どの優先順位が優先されるかを説明するドキュメントはありますか?

ルールは非常に複雑で、完全なストーリーについては C++ 標準を読む必要があります。簡単な経験則では、暗黙的な変換に複数のユーザー定義の変換を含めることはできず、(ご存知のように) 暗黙的な変換の結果を使用して、引数依存のルックアップによってテンプレートの特殊化を選択することはできません。

関連する注意事項を完全に理解しているかどうかはわかりません。誰かそれらの概要を教えてください。

私もそれらを完全には理解していません。暗黙の変換、名前の検索、テンプレートの特殊化 (およびおそらく今は思いつかないその他の要因) の間の相互作用はかなり複雑であり、ほとんどの人はそれらすべてを学習する傾向がありません。暗黙的な変換が行われない場合もあれば、予期しないときに発生する場合もあります。個人的には、ほとんどの場合、暗黙的な変換を避ける方が簡単だと思います。

パブリック メソッドの ToUnsignedLongInt と ToString を定義する方がよいのでしょうか。

不要な変換を避けるために、これはおそらく良い考えです。それらをそのままにして、必要に応じて明示的に使用することで問題を解決できます。

std::cout << std::string(x) << std::endl;

C++11 では、これらを宣言できるexplicitため、この方法でのみ使用できます。私の意見では、可能であればそれが最良の選択肢です。それ以外の場合は、あなたが提案するように明示的な変換関数を使用します。

ちなみに、 の戻り値の型は ではなく でmain()なければなりintませんvoid

于 2012-04-23T18:20:00.180 に答える