4

Consoleクラスを作成しようとしています。cinラップしcoutてクラスに入れ、<<and>>演算子をオーバーロードしたいと思います。だから私はそのようにクラスを使うことができました:

// Output
Console << "Call cout from Console" << endl;

// Input
string str;
Console >> str; // Call cin

私の最良の推測は:

class Console {
//...
public:
    ostream& operator<< (ostream& os)
    {
        cout << os;
        return &cout;
    }
    //...
};

cinしかし、それが間違っていることはわかっています。コンソールクラスをとの両方として使用するように演算子をオーバーロードするにはどうすればよいcoutですか?

4

5 に答える 5

7

ストリームマニピュレータを処理できる実用的なコードを入手しました。このIdeoneページで私のコードの動作を見ることができます

コードは次のとおりです。

#include <iostream>

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

class console {

};

template <class T> console& operator<< (console& con, const T& x) { std::cout << x; return con; }
template <class T> console& operator>>(console& con,  T& x) { std::cin >>x; return con; }
console& operator<< (console& con, manip manipulator){ std::cout<<manipulator; return con;}

int main() {
    console c;
    int a,b;
    c>>a>>b;
    c << "hello world"<<std::endl<<std::hex<<(a+b)<<std::endl;
}

実用的な答えに導いた議論をしてくれた@MooingDuckと、出発点をくれた@111111に感謝します。

于 2012-09-15T03:48:33.967 に答える
2

なぜそんなことをしたいのかわかりませんが、キャプチャする必要があるのはストリームではなく、他のタイプです。しかし、これがstd::coutとstd::cinをより便利にするためだけであれば、私は気にしません。

class console {

};

template<typename T>
console& operator<<(console con, const T& val) {
     std::cout << val;
     return con;
}

console c;
c << "hello world\n";
于 2012-09-14T23:06:33.113 に答える
2

これはあなたの質問に対する直接の答えではありませんが、おそらく私はあなたにいくつかの代替案を指摘します。

他の質問に対する私の答えを参照してください。これらすべて<<>>演算子を自分で定義するのは簡単ではありません。ただし、コンソールのstreambufを上書きすることはできます。cinとcoutを組み合わせたstreambufsを使用します。

からコンソールを派生させ、からstd::iostreamstreambufを派生させますstd::streambuf

class console_streambuf : public std::streambuf {
public:
    console_streambuf() {
        // no buffering, overflow on every char
        setp(0, 0);
    }
    virtual int_type overflow(int_type c) {
        std::cout << c;
        return c;
    }
    ...
};

class console : public std::iostream {
public:
    console() { rdbuf(&buf); }
private:
    console_streambuf buf; 
};
于 2012-09-15T00:04:37.180 に答える
1

上記の回答の多くとは異なり、テンプレートの魔法を使用して、やりたいことを行うのは非常に簡単です。

ostream(coutはostream)を使用すると、難解な黒魔術(冗談ではない)が必要になる可能性があるため、stringstreamを使用することをお勧めします。

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

struct console {
  std::stringstream  data_;

  console() : data_() {  };

  // We make ourselves a template sink so we can "take" operator<<'s.
  //  The awesome advantage to using a template like this is that the
  //  compiler will allow us to "take" any data that can be converted
  //  to a stringstream, which will handle converting int's etc.
  //  for us!
  template<typename T>
  console& operator<<(const T& what) {
    data_ << what;
    return *this;  // We must return a reference if we want to
                   //  string together more than one thing, i.e.
                   //  b << " " << 4;
  }

  void flush() {
    std::cout << data_.str();
    data_.clear();
    std::cout.flush();
  }
};

int main()
{
  int a = 4;
  console b;
  console c;
  b.data_ << 2;
  c.data_ << 4;
  //b << std::cout;  // WHAT? it's possible but stupid, prints garbage

  // Because we made the template return a reference, this will
  //  allow us to chain things just like we do with cout.
  b << " HELLO WORLD! " << "yo!" << 4;

  b << a << " " << 4.2f;

  // Compiler chokes on this. It will try to convert "console"
  //  to a stringstream which it can't.
  //b << c;

  b.flush(); // Send out the output

  // Wait for key press
  char foo[500];
  gets(foo);
}

出力:

2 HELLO WORLD! yo!44 4.2

もちろん、より多くの制御を行うことを除いて、coutと同じです。バイナリI/Oが必要な場合は、basic_ostreamとbasic_istreamsの使用を開始できますが、本当に必要な場合を除いて、使用しないことをお勧めします。

于 2012-09-15T02:05:58.690 に答える
-1

オーバーロードされた演算子関数は、左右で呼び出す特定の型で宣言する必要があります。したがって、、、などが必要になりoperator<< (int)ます。operator<< (double)operator<< (const std::string &)

それらをcinとcoutに渡すだけの場合は、次のようなテンプレートメンバー関数を使用して入力を節約できます。

template <class T> Console& operator<< (const T& x) { cout << x; return *this; }

[Andréに指摘してくれてありがとう、Console&を返す必要があるので、次のように呼び出しをつなぎ合わせることができますConsole << a << b;]

于 2012-09-14T23:10:14.453 に答える