Пользовательский ostream печатает только последнюю строку цепочки `<<`
Я пытаюсь реализовать класс с пользовательским оператором потока, и наследуется от него, чтобы иметь базовый класс и производный класс с различными потоками. Тогда я перегружаю <<
оператор для использования хранится ostream
,
Это рабочий пример кода:
#include <string>
#include <memory>
#include <ostream>
#include <iostream>#
#include <fstream>
class Sink {
public:
Sink() {
m_stream = std::unique_ptr<std::ostream>(new std::ostream(std::cout.rdbuf()));
};
template<typename T>
std::ostream& operator<<(const T& obj) {
return *m_stream;
}
protected:
std::unique_ptr<std::ostream> m_stream;
};
class FileSink : public Sink {
public:
FileSink() {
m_stream = std::unique_ptr<std::ostream>(new std::ofstream("file.txt"));
}
};
int main() {
Sink s;
FileSink fs;
s << "First console string " << "second console string";
fs << "First file string " << "second file string";
return 0;
}
С Sink class
Я пишу на консоли, с FileSink
на файл.
Проблема в том, что с этим кодом я печатаю только последнюю строку каждой инструкции.
В консоли я вижу следующий вывод:
second console string
в то время как в файле я вижу этот вывод:
second file string
Что я делаю не так и как можно распечатать ожидаемый результат?
2 ответа
Ваш operator<<
ничего не делает и возвращается std::ostream&
, Тогда вы подаете заявку std::ostream::operator<<
к этому std::ostream&
, Ожидаемая вещь!
Стандартный способ сделать то, что вы хотите:
template<typename T>
Sink & Sink::operator<<(const T& obj) {
*m_stream << obj;
return *this;
}
template<typename T>
FileSink & FileSink::operator<<(const T& obj) {
*m_stream << obj;
return *this;
}
Для предотвращения дублирования кода вы можете использовать наследование. Может дублировать std::stream
Схема наследования, я думаю.:)
template<typename T>
std::ostream& operator<<(const T& obj) {
*m_stream << obj; // you missed this
return *m_stream;
}
Кроме того, вы можете определить operator<< как функцию, не являющуюся членом.
template <typename T>
Sink& operator<<(Sink &sink, const T &obj) {
*(sink.m_stream) << obj;
return sink;
}
и сделай это другом Раковины:
class Sink {
template <typename T>
friend Sink& operator<<(Sink &sink, const T &obj);
// other code.
}