![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| T0ohtik |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 115 Регистрация: 9.2.2008 Репутация: нет Всего: 1 |
Доброй ночи, товарищи! Возникла задача написать базовый, абстрактный класс. И перегрузить опретацию <<. Получается, что для достижения этой целин надо написать виртуальную, дружественную, нулевую функцию. Возможно ли такое или я что то нагородил?
|
|||
|
||||
| vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 13 Всего: 56 |
делаешь виртуальный\чисто виртуальный оператор в базовом классе, например +=, потом переопределяешь его в потомке. И делаешь внешнюю ф-ию например +, и все..
|
|||
|
||||
| Annihilator |
|
|||
![]() bytegrinder ![]() ![]() Профиль Группа: Участник Сообщений: 493 Регистрация: 21.11.2006 Где: Омск Репутация: 1 Всего: 3 |
Попробуй так
Это сообщение отредактировал(а) Annihilator - 19.7.2008, 09:53 -------------------- Если вы не можете сделать хоpошyю пpогpаммy, сделайте, чтобы она по кpайней меpе выглядела хоpошо |
|||
|
||||
| Torsten |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 174 Регистрация: 10.6.2008 Где: Pskov Репутация: 3 Всего: 7 |
У меня почти такой же вариант, как и у Annihilator, только оператор << не дружественная функция.
Это сообщение отредактировал(а) Torsten - 19.7.2008, 11:25 --------------------
We have no begining, we have no end. We are infinite. |
|||
|
||||
| Ulysses4j |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 304 Регистрация: 6.6.2007 Где: Ростов-на-Дону Репутация: 4 Всего: 10 |
Я за версию Annihilator, хотя версия Torsten соответствует тому, что у Мейерса. Мотивация такая: out не предназначена для внешних пользователей — клиенты этой иерархии классов должны использовать operator<< — но есть одно исключение, сам operator<<: это значит, надо делать out закрытой, а operator<< френдить.
Но вместо out лучше print, да (со строчной буквы!). -------------------- Communication is critical to the job of a programmer. C. Jazdzewski. Fatherly Advice To New Programmers |
|||
|
||||
| vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 13 Всего: 56 |
Насколько я помню Майерс за инкапсуляцию, а френды ее нарушают. Вообще френды надо юзать при крайней необходимости, я считаю. |
|||
|
||||
| Ulysses4j |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 304 Регистрация: 6.6.2007 Где: Ростов-на-Дону Репутация: 4 Всего: 10 |
Есть еще такая мотивировка. Изначально operator<< хочется сделать членом класс (так и Мейерс, кстати, начинает рассказывать, но это очевидно и из общих соображений: функция вывода в поток должна иметь доступ к представлению, чтобы его непосредственно и выводить). Но если поступить так, то не получится реализовать привычную идиому os << foo; (придется задом наперед). Вот и идут на этот финт с print. Но если вы изначально хотели предоставить operator<< доступ к реализации, то чего уж бояться делать его френдом: ведь член это более близкая связь чем френд. С print есть еще проблема: пользователь класса будет смотреть и видеть две функции одного назначения: print и operator<<. Это ненужное раздувание интерфейса, умножение сущностей без необходимости (привет Оккаму). В случае с закрытой print для пользователя есть только одна функция выполняющая одну работу. Все предельно ясно. И все-таки меня терзают смутные сомнения, что я где-то читал вариант с закрытой print. Что за память... -------------------- Communication is critical to the job of a programmer. C. Jazdzewski. Fatherly Advice To New Programmers |
|||
|
||||
| UnrealMan |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
Однако, тот, кто наследуется, должен знать о существовании print у базового класса. Т.е. print должна быть задокументирована. |
|||
|
||||
| Ulysses4j |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 304 Регистрация: 6.6.2007 Где: Ростов-на-Дону Репутация: 4 Всего: 10 |
Да, дельное замечание. Под клиентами я, разумеется, понимал классы, непосредственно использующие объекты рассматриваемого класса (с “виртуальной” функцией вывода в поток) и его наследников. Все-таки по умолчанию я предполагаю, что человек не наследуется от классов чужой библиотеки (наследование реализации многажды поруганная стратегия... впрочем, как и френдизм
-------------------- Communication is critical to the job of a programmer. C. Jazdzewski. Fatherly Advice To New Programmers |
|||
|
||||
| Torsten |
|
||||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 174 Регистрация: 10.6.2008 Где: Pskov Репутация: 3 Всего: 7 |
И чем же она нарушает инкапсуляцию ? Тем что выводит свои данные в поток ? Ее обычно и создают, чтобы выводить информацию, а не скрывать ее. Можно создать класс printable, у которого будет переопределен оператор << и вызывается виртуальная функция print. Унаследованный класс должен будет переопредилить функцию print, и в тоже самое время ему не нужно будет определять оператор <<, т.к. он реализован для класса printable. Когда пользователь будет смотреть архитектуру класса он не будет видеть лишнего и сам интерфейс не будет раздуватся, т.к. достаточно будет в проивзодных классах определить только 1 функцию. Это мнение ошибчно. Для того, чтобы это понять нужно понять "принцип интерфейса". В случае ostream & operator <<(ostream & strm, const Foo & foo) { /*код для вывода в поток */} в соотвествии с принципом интерфейса. Так как operator << упоминает Foo - он является логической часть Foo. operator << упоминает ostream, поэтому operator << зависит от ostream. operator << является логической частью Foo и зависит от ostream, следовательно Foo зависит от ostream. Таким образом реализация посредством френд оператора <<, ничем не лучше функции Print. А Print как я уже и писал выше имеет преимущество перед френд оператором в том, что в поток корректно выводтся все производные от X классы, даже при передаче оператору << ссылки производных классов.
Это вопрос стиля и правил разработки принемаемых перед созданием проекта. Это сообщение отредактировал(а) Torsten - 20.7.2008, 00:46 --------------------
We have no begining, we have no end. We are infinite. |
||||
|
|||||
| Ulysses4j |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 304 Регистрация: 6.6.2007 Где: Ростов-на-Дону Репутация: 4 Всего: 10 |
Нет, не тем что выводит данные в поток, а тем, что создавалась она только для использования в operator<<, а а выложив ее в public, ей смогут пользоваться клиенты класса. Ее создают не для того, чтобы выводить данные в поток — видимо, вы позабыли, что print создавалась, чтобы задействовать механизм виртуальности, это деталь реализации operator<<, роль которого как раз вывод в поток — с точки зрения клиента. Вы не понимаете: это не преимущество print, а ее назначение: обеспечивать виртуальность. Если бы она этого не делала, обошлись бы без нее. Ну, или без operator<<. Если уж решили его сделать, то он должен быть единственным средством вывода в поток. “Принцип интерфейса” не осилил Еще один аргумент закрытия print это совет из Стандартов кодирования Саттера&Александреску, повторяемый у Саттера в More Exceprtional и Дьюхерста в Готчах (или если по хронологии, то наоборот, кажется): делайте виртуальные функции закрытыми (идиома non-virtual interface, NVI). В данном случае невиртуальный интерфейс это operator<<, а спрятанная по канонам Саттера-Александреску-Дьюхерста виртуальность это print. -------------------- Communication is critical to the job of a programmer. C. Jazdzewski. Fatherly Advice To New Programmers |
|||
|
||||
| Torsten |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 174 Регистрация: 10.6.2008 Где: Pskov Репутация: 3 Всего: 7 |
Ну и что дальше ? Ну могут они данные вывести, но данные изменять не могут и кроме того они понятие не имеют о том что выводится, так что здесь все нормально. Ну если вы не понимаете, тогда я обьясню на коде.
Будет использоватся оператор вывода для абстрактного класса Message. Если реализовывать с помощью функции Print, то во-первых не нужно будет писать для каждого класса оператор <<, а во-вторых самое главное, всегда будут выводится реальные данные, то есть SystemMessage и UserMessage, т.к. функция Print будет вызвана у них. --------------------
We have no begining, we have no end. We are infinite. |
|||
|
||||
| Ulysses4j |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 304 Регистрация: 6.6.2007 Где: Ростов-на-Дону Репутация: 4 Всего: 10 |
Так вы полагаете что инкапсуляция означает невозможность изменить данные? Ну, спешу вас огорчить, это намного более общее понятие: инкапсуляция подразумевает сокрытие реализации класса и его артефактов (в C++ — в частности, тесно связанных с классом свободных функций). Я надеюсь, вы когда-нибудь использовали private-методы. Это тоже инкапсуляция. Надеюсь, когда-нибудь использовали private-константы внутри класса: их можно было бы открыть, потому что их изменить нельзя (хаки с const-кастом не берем, можно рассмотреть другие ОО-языки, в которых подобных cast-ов нет). Однако, закрытые константы используются. Это тоже инкапсуляция. И скрытие деталей того, как виртуализирована operator<<, то есть закрытие print, это тоже инкапсуляция. О! Вы попытались объяснить мне идиому виртуальной свободной функции, как она описана у Мейерса (см. мою ссылку выше)! Это сообщение отредактировал(а) Ulysses4j - 20.7.2008, 21:49 -------------------- Communication is critical to the job of a programmer. C. Jazdzewski. Fatherly Advice To New Programmers |
|||
|
||||
| T0ohtik |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 115 Регистрация: 9.2.2008 Репутация: нет Всего: 1 |
Извините, что долго отсутствовал. Спасибо всем кто ответил!
|
|||
|
||||
| UnrealMan |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
||||
|
||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |