Как перегрузить оператор <<?
-
13-09-2019 - |
Вопрос
Я намерен вызывать функцию всякий раз, когда m_logger<<"hello"<<"world"
называется.m_logger имеет тип потока.
Поэтому я решил перегрузить << следующей подписью
friend ofstream& operator<<(ofstream &stream,char *str);
Однако компилятор vc выдает следующую ошибку:
ошибка C2666:'оператор <<':6 перегрузок имеют аналогичные преобразования
Есть ли другой способ добиться этого, моя цель - перенаправить всю операцию записи в объект ofstream на другую функцию?
Создание объекта моего собственного класса работает для меня, однако как я могу заставить его работать как обычный объект потока, который преобразует все типы, определенные системой, в строки или char*.я знаю, что одним из подходов было бы перегрузить оператор для каждого типа, но есть ли более чистый подход
Решение
Проблема в том, что ofstream
уже перегружен таким образом.Если ты сделаешь mlogger
нового типа, обладающего ofstream
, то вы можете сделать это:
class mlogger_t {
public:
ofstream stream;
...
}
mlogger_t& operator<<(mlogger_t& stream, const string& str) {
stream.stream << str;
...
}
//EDIT: here is how to make this work for other types too using templates:
template<typename T> mlogger_t& operator<<(mlogger_t& stream, T val) {
stream.stream << val;
}
...
mlogger_t mlogger;
mlogger << "foo";
Кроме того, вам обязательно следует использовать const string&
(как я сделал в этом примере), а не строку в стиле C.Если вы Действительно нужно, чтобы это было в стиле C, хотя бы используйте const char *
.
Другие советы
«перегрузка» — это не «переопределение».Вы можете перегрузить функцию или оператор для аргументов разных типов;вы не можете переопределить существующую функцию или оператор своей собственной реализацией (кроме переопределения виртуальных функций, что, очевидно, сильно отличается).Единственными исключениями являются operator new
и operator delete
, где можно переопределить встроенные.
Вы можете изменить тип объекта m_logger.
В зависимости от того, почему вы хотите перегрузить оператор<<, правильным решением будет либо
- использовать в качестве целевого потока другой тип, отличный от потомка ostream;в этом случае вам придется написать все операторы << самостоятельно, но вы можете получить помощь от шаблонов, если хотите пересылать по умолчанию.
Так:
template <typename T>
myStream& operator<<(myStream& s, T const& v)
{
s.getStream() << v;
}
и вы увидите, что манипуляторы не соответствуют шаблону, поэтому вам также понадобится что-то вроде:
myStream& operator<<(myStream& fl, std::ostream& (*fn)(std::ostream&))
{
s.getStream() << fn;
}
- написать свой собственный потоковый буфер, который делегирует ввод-вывод в std::filebuf (это слишком сложно, чтобы приводить пример здесь, поищите в Интернете - фильтрация потокового буфера является хорошим ключевым словом для этого.Если я правильно помню, у boost есть вспомогательная библиотека, которая может оказаться полезной.Обратите внимание, что в этом случае вы, вероятно, в конечном итоге будете использовать другой тип, а именно fstream, но который будет потомком ostream.
Что вам нужно сделать, это создать класс, а затем определить operator<<
.Перегрузка оператора должна содержать хотя бы один определяемый пользователем тип.Точно так же вы не можете написать новый operator+(int, int)
.