поток — C ++ Обтекание cin и cout в классе — Перегрузка & lt; & lt; и & gt; & gt; операторы

Я пытаюсь сделать класс консоли. Я хотел бы завернуть cin а также cout в классе и перегрузить << а также >> операторы. Так что я мог бы использовать класс как таковой:

// 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 в качестве обоих cin а также cout?

3

Решение

Я получил рабочий код, который может обрабатывать потоковые манипуляторы. Вы можете увидеть мой код в действии на этой странице 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 за начальную точку.

5

Другие решения

Я не знаю, почему хотел бы сделать такую ​​вещь, но это не поток, который вам нужно захватить, а другой тип. Но если это просто для того, чтобы сделать 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";
2

Это не прямой ответ на ваш вопрос, но, возможно, я укажу вам какую-то альтернативу.

См мой ответ на какой-то другой вопрос. Чтобы определить все это <<а также >> Операторы это не очень просто. Однако вы можете перезаписать streambuf для консоли. Используйте комбинированные потоковые буферы cin и cout,

Получите вашу консоль от std::iostream и ваш поток из 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;
};
2

Вопреки многим ответам выше, делать то, что вы хотите, довольно просто, используя магию шаблонов.

Я бы порекомендовал использовать струнный поток, потому что использование 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, за исключением, конечно, с большим контролем.
Вы можете начать использовать basic_ostream’s и basic_istreams, если хотите использовать бинарный ввод / вывод, но я бы рекомендовал против этого, если вам это действительно не нужно.

1

Перегруженные операторные функции должны быть объявлены с конкретными типами, с которыми вы будете вызывать их слева и справа. Так что вам понадобится operator<< (int), operator<< (double), operator<< (const std::string &), так далее.

Если вы действительно просто собираетесь передать их в cin и cout, вы можете сохранить ввод с помощью функции-члена шаблона, например:

template <class T> Console& operator<< (const T& x) { cout << x; return *this; }
[спасибо Андре за то, что он указал, что должен вернуть Консоль& так что вы можете связать вместе звонки, как Console << a << b; ]
-1
По вопросам рекламы [email protected]