C ++在类中包装cin和cout - 重载<<和>>运营商

时间:2012-09-14 23:01:16

标签: c++ stream operator-overloading cout cin

我正在尝试制作一个Console类。我想在课程中包含cincout并重载<<>>运算符。所以我可以这样使用这个类:

// 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;
    }
    //...
};

但我知道这是错的,我如何重置运营商以将Console类用作cincout

4 个答案:

答案 0 :(得分: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";

答案 1 :(得分:2)

这不是你问题的直接答案,但也许我指出了一些替代方案。

请参阅我的answer其他问题。要自己定义所有这些<<>>运算符并不容易。但是,您可以覆盖控制台的streambuf。使用cin和cout的组合streambufs,

std::iostreamstd::streambuf

的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; 
};

答案 2 :(得分:1)

与上面的许多答案相反,使用模板的魔力,做你想做的事情非常简单。

我建议使用字符串流,因为使用ostream(cout是ostream)可能需要神秘的黑魔法(不是玩笑)。

#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,但除非你真的需要它,否则我建议不要使用它。

答案 3 :(得分:-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&amp;所以你可以将Console << a << b;]

之类的电话串在一起
相关问题