Пользовательский 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.
}
Другие вопросы по тегам