Форум программистов, компьютерный форум CyberForum.ru

Наследование от ofstream и перегрузка << - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.90
VVildVVolf
82 / 1 / 0
Регистрация: 08.10.2012
Сообщений: 54
14.07.2015, 14:36     Наследование от ofstream и перегрузка << #1
Добрый день, гуглил на английском языке, но ответа не попалось. Предыстория: некий объекта принимает в качестве параметра ссылку на ostream, куда подсовывается ofstream. Задача в том, что перед действием << требуется сделать дополнительные телодвижения, а точнее обработать данные, которые направляются на выход. Я вижу решение таким, что нужно наследоваться от ofstream и переопределить <<. как это правильно делается нагуглить не удалось. Буду рад приведенным примерам или ссылкам на статьи об этом. Спасибо.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7954 / 4716 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
14.07.2015, 14:39     Наследование от ofstream и перегрузка << #2
Наследоваться точно не надо. Не понятна проблема, в чем проблема обработать данные в отдельной функции/в перегруженном операторе вывода?
VVildVVolf
82 / 1 / 0
Регистрация: 08.10.2012
Сообщений: 54
14.07.2015, 14:44  [ТС]     Наследование от ofstream и перегрузка << #3
проблема в том, что объект который отправляет данные уже "делает это" в ofstream. Есть способ не переписывая "источник данных" заставить отправлять их в какой-то не наследуемый от ofstream объект?
п.с. я просто новичек в С++, мож не знаю каких-то фишек...

грубо говоря, источник данных имеет возможность писать список имён в ofstream. сейчас задача состоит в том, чтоб некоторые имена блокировать (как буд-то их нет)
vxg
Модератор
 Аватар для vxg
2725 / 1736 / 172
Регистрация: 13.01.2012
Сообщений: 6,501
14.07.2015, 14:45     Наследование от ofstream и перегрузка << #4
Цитата Сообщение от VVildVVolf Посмотреть сообщение
некий объекта принимает в качестве параметра ссылку на ostream
не факт что этот объект делает вывод через << - речь идет именно о передачи объекту ссылки или оператор << перегружен для этого объекта?
VVildVVolf
82 / 1 / 0
Регистрация: 08.10.2012
Сообщений: 54
14.07.2015, 14:57  [ТС]     Наследование от ofstream и перегрузка << #5
исходники для меня открыты, так что я знаю, что вывод делается через <<
внутри что-то вроде
C++
1
2
3
4
class DataSource{
public:
    void print(ostream& output){output<<"{name:'Fedya'}"};
}
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7954 / 4716 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
14.07.2015, 15:34     Наследование от ofstream и перегрузка << #6
VVildVVolf, Я бы таки предпочел весь код оператора вывода, ибо непонятно, что вы хотите фильтровать в функции print на данный момент. Но как бы то ни было - есть доступ к изменению print - изменяйте, нет - пишите функцию, которая будет зваться перед выводом и фильтровать нужные имена.
Можно конечно и boost::iostreams попробовать поюзать, но это дикий оверкил и бессмысленно.
VVildVVolf
82 / 1 / 0
Регистрация: 08.10.2012
Сообщений: 54
14.07.2015, 15:52  [ТС]     Наследование от ofstream и перегрузка << #7
Код немного размазан по проекту, и, если честно, ostream передаётся в конструктор объекта "источник данных". на данный момент в функции print я хочу фильтровать по сути наборы символов, которые получаются на выходе (просто обработать вывод). если непонятна цель задачи, тогда попробую поставить более простую:
C++
1
2
3
4
5
6
7
8
9
class DataSource{
public:
    DataSource(ostream& s):output(s){};
    void Print(){
        output<<"aaSSvvKK";
    }
private:
     ostream& output;
}
на данный момент передаётся ofstream (пишуший в файл), то, что запишет метод Print. нужно доработать так, чтоб в файл писалась та же строка, только в ЛоверКейсе. ну чтобы была возможность и по старому, и по новому.
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7954 / 4716 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
14.07.2015, 16:02     Наследование от ofstream и перегрузка << #8
C++
1
2
3
DataSource ds(stream);
ds.ToLower();
dt.Print();
Или же
C++
1
ToLower(ds);
Почему не так? Фильтровать-то можно прям исходящий поток, но это несколько геморойно.
VVildVVolf
82 / 1 / 0
Регистрация: 08.10.2012
Сообщений: 54
14.07.2015, 16:13  [ТС]     Наследование от ofstream и перегрузка << #9
ведь задача ЛоверКейса - это просто пример я бы хотел предусмотреть ситуацию, чтобы можно было накладывать разные фильтры. DataSource не хотелось бы модифицировать, потому что это по сути не его зона ответственности, он в данной ситуации должен просто выдавать "грязные данные как есть".
насчет геморно - я об этом начал догадываться, когда не смог нагуглить пример этого процесса...
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7954 / 4716 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
14.07.2015, 16:30     Наследование от ofstream и перегрузка << #10
Ну. Хм. Тогда действительно пишем наследника от ofstream/ostream перегружаем оператор вывода как нам надо, подаем в конструктор DataSource объект наследника.
vxg
Модератор
 Аватар для vxg
2725 / 1736 / 172
Регистрация: 13.01.2012
Сообщений: 6,501
14.07.2015, 16:31     Наследование от ofstream и перегрузка << #11
Цитата Сообщение от VVildVVolf Посмотреть сообщение
нужно доработать так
первое что приходит в голову - наследовать от streambuf, переделывать там виртуальные функции, создавать наследника ostream основанного на этом streambuf и подсовывать его. но в streambuf будет весело все это дело ловить

Добавлено через 35 секунд
Цитата Сообщение от ForEveR Посмотреть сообщение
пишем наследника от ofstream/ostream перегружаем оператор вывода как нам надо
они вроде как не виртуальные. перегрузка ничего не даст
VVildVVolf
82 / 1 / 0
Регистрация: 08.10.2012
Сообщений: 54
14.07.2015, 16:35  [ТС]     Наследование от ofstream и перегрузка << #12
таки изначально вопрос стоял "как это сделать"... но я очень рад, что так быстро пришли к взаимопониманию =)

п.с. меня натолкнули на мысль, как вариант можно толкать stringstream, а потом его сувать в фильтры, это лучше/хуже?
п.с.с. На будущее всё равно хотелось бы увидеть решение изначально поставленной задачи, ибо нельзя пробелы оставлять открытыми...
vxg
Модератор
 Аватар для vxg
2725 / 1736 / 172
Регистрация: 13.01.2012
Сообщений: 6,501
14.07.2015, 16:43     Наследование от ofstream и перегрузка << #13
Цитата Сообщение от VVildVVolf Посмотреть сообщение
можно толкать stringstream
толкать в поток а потом пропускать его через любые комбайны это здравая мысль фактически ничем не отличающаяся от копания в streambuf
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7954 / 4716 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
14.07.2015, 16:54     Наследование от ofstream и перегрузка << #14
Очень простой пример фильтрации.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <functional>
#include <algorithm>
 
class formatting_ostream
{
public:
   typedef std::function<std::string(const std::string&)> filter_t;
   formatting_ostream(std::ostream& stream, const filter_t& filter) : stream_(stream), filter_(filter)
   {
   }
   formatting_ostream& operator << (const std::string& value)
   {
      const std::string filtered = filter_(value);
      stream_ << filtered << std::endl;
      return *this;
   }
private:
   std::ostream& stream_;
   filter_t filter_;
};
 
class source
{
public:
   source(formatting_ostream& stream) : stream_(stream)
   {
   }
   void print()
   {
      stream_ << "HeLLo";
   }
private:
   formatting_ostream& stream_;
};
 
int main()
{
   auto to_lower = [](const std::string& v) -> std::string
   {
      std::string result;
      std::transform(v.begin(), v.end(), std::back_inserter(result), tolower);
      return result;
   };
   formatting_ostream stream(std::cout, to_lower);
   source s(stream);
   s.print();
}
Конечно, если source должен конструироваться именно от ostream это будет значительно сложнее.

Добавлено через 5 минут
По поводу того как правильно должен быть реализован formatting_ostream можно посмотреть на boost/log.
VVildVVolf
82 / 1 / 0
Регистрация: 08.10.2012
Сообщений: 54
14.07.2015, 16:56  [ТС]     Наследование от ofstream и перегрузка << #15
в том-то и дело, что он конструируется от ostream, ибо этот объект - место куда сливаются в итоге данные...

"фактически ничем не отличающаяся от копания в streambuf" - разница лишь в том, что решение на основе stringstream гуглить проще, а альтернативное (как мне пока что кажется) лаконичнее, поэтому хотелось бы увидеть пример наследования и оверрайда..
vxg
Модератор
 Аватар для vxg
2725 / 1736 / 172
Регистрация: 13.01.2012
Сообщений: 6,501
14.07.2015, 16:56     Наследование от ofstream и перегрузка << #16

Не по теме:

Цитата Сообщение от ForEveR Посмотреть сообщение
auto to_lower = [](const std::string& v) -> std::string
мои глаза! мои прекрасные глаза!! до сих пор не могу привыкнут к этим штукам. и никогда наверное не привыкну

Цитата Сообщение от ForEveR Посмотреть сообщение
source должен конструироваться именно от ostream
думаю это реально будет в 500 раз сложнее
VVildVVolf
82 / 1 / 0
Регистрация: 08.10.2012
Сообщений: 54
14.07.2015, 16:59  [ТС]     Наследование от ofstream и перегрузка << #17
"мои глаза! мои прекрасные глаза!! до сих пор не могу привыкнут к этим штукам. и никогда наверное не привыкну "
Вы, батенька, наверное на C# не программировали...

ну сложнее-не сложнее, на форуме геморно представить?
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7954 / 4716 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
14.07.2015, 17:07     Наследование от ofstream и перегрузка << #18
VVildVVolf, Если через streambuf то действительно много разбираться и писать кода.
Через stringstream понятное дело довольно просто, несильно отличается от моего в общем и целом.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <functional>
#include <algorithm>
#include <sstream>
 
class source
{
public:
   source(std::ostream& stream) : stream_(stream)
   {
   }
   void print()
   {
      stream_ << "HeLLo" << std::endl;
   }
private:
   std::ostream& stream_;
};
 
class filter
{
public:
   typedef std::function<std::string(const std::string&)> filter_t;
   filter(std::ostringstream& in_stream, std::ostream& out_stream, const filter_t& filter) :
      in_stream_(in_stream), out_stream_(out_stream), filter_(filter)
   {
   }
   void print()
   {
      out_stream_ << filter_(in_stream_.str());
   }
private:
   std::ostringstream& in_stream_;
   std::ostream& out_stream_;
   filter_t filter_;
};
 
int main()
{
   std::ostringstream fstream;
   source s(fstream);
   s.print();
   auto to_lower = [](const std::string& v) -> std::string
   {
      std::string result;
      std::transform(v.begin(), v.end(), std::back_inserter(result), tolower);
      return result;
   };
   filter filt(fstream, std::cout, to_lower);
   filt.print();
}
VVildVVolf
82 / 1 / 0
Регистрация: 08.10.2012
Сообщений: 54
15.07.2015, 11:35  [ТС]     Наследование от ofstream и перегрузка << #19
Через stringstream в принципе понятно как делать, проблема только в юзабельности: чел который будет читать код увидит создание буфера, передачу его в DataSource (буфер становится к тому ж out параметром), потом на его основе создает фильтр....
При наследовании: на основе фильтра создается выходной поток и отдается в DataSource как способ вывода - все очевидно

Добавлено через 16 часов 51 минуту
Ещё есть такой момент, если сначала всё заталкивать в stringstream - то и обрабатывать всё это дело придется "всем скопом", после окончания вывода, а при перегрузке streambuf я так понимаю можно "по мере поступления"
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.07.2015, 12:00     Наследование от ofstream и перегрузка <<
Еще ссылки по теме:

Перегрузка оператора = и +=, используя наследование классов C++
Перегрузка ifstream и ofstream? C++
C++ Перегрузка ifstream и ofstream для работы с файлами в little-endian формате?
Перегрузка ofstream, istream C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7954 / 4716 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
15.07.2015, 12:00     Наследование от ofstream и перегрузка << #20
Вариант через streambuf.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
#include <array>
#include <functional>
#include <algorithm>
 
class formatting_streambuf : public std::streambuf
{
public:
   typedef std::function<std::string(const std::string&)> formatter_t;
 
   formatting_streambuf(std::streambuf* out_buf, const formatter_t& formatter) : out_buf_(out_buf), formatter_(formatter), array_{}
   {
      setp(array_.begin(), array_.end());
   }
 
   ~formatting_streambuf()
   {
      const std::string buffer = std::string(array_.begin(), pptr() - array_.begin());
      const std::string formatted = formatter_(buffer);
      out_buf_->sputn(formatted.c_str(), formatted.size());
   }
private:
   std::streambuf* out_buf_;
   formatter_t formatter_;
   std::array<char, 1024> array_;
};
 
class source
{
public:
   source(std::ostream& stream) : stream_(stream)
   {
   }
 
   void print()
   {
      stream_ << "HeLlO" << std::endl;
   }
 
   std::ostream& get_stream() const { return stream_; }
private:
   std::ostream& stream_;
};
 
template<typename T>
void print_filtered(source& s, const T& filter)
{
   std::streambuf* old_buf = s.get_stream().rdbuf();
   formatting_streambuf streambuf(old_buf, filter);
   s.get_stream().rdbuf(&streambuf);
   s.print();
   s.get_stream().rdbuf(old_buf);
}
 
int main()
{
   auto to_lower = [](const std::string& v) -> std::string
   {
      std::string result;
      std::transform(v.begin(), v.end(), std::back_inserter(result), tolower);
      return result;
   };
   source s(std::cout);
   s.print();
   print_filtered(s, to_lower);
}
Можно еще сделать так же потомка std::ostream, который будет работать с данным streambuf, но у меня не сложилось.

Добавлено через 2 минуты
VVildVVolf, По мере поступления по факту довольно сложно. Вот документация: http://en.cppreference.com/w/cpp/io/basic_streambuf
Можно перегрузить xsputn, но, это работает только если идет вывод строки, если же идет вывод символа - зовется sputc, который не перегрузить.
Yandex
Объявления
15.07.2015, 12:00     Наследование от ofstream и перегрузка <<
Ответ Создать тему
Опции темы

Текущее время: 05:27. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru