3

ostream オブジェクトに渡されたシステム定義のユーザー型は、文字列または char* に変換されますか?

cout<<4<<"Hello World"; のように。

これはどのように達成されますか? << 演算子はすべての型に対してオーバーロードされていますか? オーバーロードされた汎用関数を 1 つだけ使用してそれを達成する方法はありますか? つまり、1 つのパラメーター (void* など) を持つオーバーロードされたオペレーター メソッドを 1 つだけ持つことができ、そのメソッド内で整数を char* に型キャストする方法を決定できます。

テンプレートieを使用して演算子<<をオーバーロードすると、部分的に機能しました

class UIStream
{
private:
 ofstream stream;
public:
 UIStream();
 ~UIStream();
 template <typename T>
 UIStream& operator << (const T);
};

だからこれはうまくいく

 UIStream my_stream;
 my_stream<<"bcd"<10;

ただし、これを行うとコンパイラエラーが発生します

my_stream <<endl;

エラー C2678: バイナリ '<<' : 'UIStream' 型の左側のオペランドを取る演算子が見つかりません (または、受け入れ可能な変換がありません)

std::endl もオブジェクトの型ではありませんか?

4

4 に答える 4

11

あなたの質問を読み直した後(この回答のコメントの結果として)、あなたが望むのは文字列への変換(ここの他の回答の私の仮定)だけでなく、内部のストリームへの転送であることに気付きました。

さて、達成したいことは単純ではなく、ほとんどの場合やり過ぎかもしれません。[make_string][3]私が持っている(内部に転送する)実装ではostringstream、マニピュレータを渡すことを許可していません。ユーザーが新しい行を追加したい場合 (Linux で開発しています)、'\n' 文字を渡すだけです。

あなたの問題は、マニピュレータ(std::hexstd::endl...)の転送です。あなたの operator<< は、型 T の定数インスタンスを取るように定義されていますが、マニピュレーターは関数ポインターであり、コンパイラーはそれをメソッドと照合することができません。

std::basic_ostreamマニピュレータは、テンプレートを操作する関数です。basic_ostreamテンプレートとクラスは次のostreamように定義されています。

template <typename TChar, typename TTraits = char_traits<TChar> >
class basic_ostream;

typedef basic_ostream<char> ostream;
// or
// typedef basic_ostream<wchar_t> if using wide characters

次に、std::ostream に渡すことができる可能なマニピュレータは次のとおりです。

typedef std::ostream& (*manip1)( std::ostream& );

typedef std::basic_ios< std::ostream::char_type, std::ostream::traits_type > ios_type;
typedef ios_type& (*manip2)( ios_type& );

typedef std::ios_base& (*manip3)( std::ios_base& );

マニピュレータを受け入れたい場合は、クラスでそのオーバーロードを提供する必要があります。

class mystream
{
//...
public:
   template <typename T> 
   mystream& operator<<( T datum ) {
      stream << datum;
      return *this
   }
   // overload for manipulators
   mystream& operator<<( manip1 fp ) {
      stream << fp;
      return *this;
   }
   mystream& operator<<( manip2 fp ) {
      stream << fp;
      return *this;
   }
   mystream& operator<<( manip3 fp ) {
      stream << fp;
      return *this;
   }
};

特に、endl の署名 (必要な唯一の署名である可能性があります) は次のとおりです。

template <typename Char, typename Traits>
std::basic_ostream<Char,Traits>& 
   std::endl( std::basic_ostream<Char,Traits>& stream );

manip1したがって、関数のタイプに該当します。その他、std::hexさまざまなカテゴリに分類されるなど (manip3この特定のケースでは)

于 2009-07-15T22:34:22.703 に答える
2

オーバーロードされた関数は1つだけです。void *それは役に立たないので、それはかかりません。1つのデータ型を使用する場合、オーバーロードされず、型に変換された後にのみ入力値が表示されます。つまり、たとえば、を変換する方法を制御することはできませんint

たとえば、anintとaの間で異なる動作char *が必要な場合は、関数が取得している型を何らかの方法で通知し、値を渡す必要があります。これは、オーバーロードされた関数またはテンプレート関数が行うこととまったく同じです。

于 2009-07-15T20:33:46.503 に答える
2

1つのパラメーター(void *など)を持つオーバーロードされた演算子メソッドが1つだけあり、そのメソッド内で整数をchar*に型キャストする方法を決定します。

いいえ、できません。void *には型情報が含まれていないため、実際にどの型を指しているのかを判断する方法はありません。

于 2009-07-15T20:29:42.080 に答える
1

<< 演算子はすべての型に対してオーバーロードされていますか?

はい

オーバーロードされた汎用関数を 1 つだけ使用してそれを達成する方法はありますか?

この質問は意味がありません..関数が1つだけ必要ですか、それともオーバーロードされた関数が必要ですか?

于 2009-07-15T20:20:09.353 に答える