![]() |
|
Модераторы: 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 |
||||
|
||||
| Ulysses4j |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 304 Регистрация: 6.6.2007 Где: Ростов-на-Дону Репутация: 4 Всего: 10 |
Ну, если считаете необходимым вызывать в потомках, делайте protected. Я же говорю: видимость должна отражать назначение.
Ну-ну, бедные-бедные ребята, эти авторы красных книжек с автором серии во главе: ушли лесом... -------------------- Communication is critical to the job of a programmer. C. Jazdzewski. Fatherly Advice To New Programmers |
|||
|
||||
| UnrealMan |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
||||
|
||||
| Ulysses4j |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 304 Регистрация: 6.6.2007 Где: Ростов-на-Дону Репутация: 4 Всего: 10 |
А, то есть вы не осили букварь и теперь кругом видите фиги?
-------------------- Communication is critical to the job of a programmer. C. Jazdzewski. Fatherly Advice To New Programmers |
|||
|
||||
| UnrealMan |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
Неумение внимательно читать книги, равно как и отсутствие самокритики, - это твоя проблема, а мне плевать на чужие проблемы :p Это сообщение отредактировал(а) UnrealMan - 21.7.2008, 14:35 |
|||
|
||||
| Ulysses4j |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 304 Регистрация: 6.6.2007 Где: Ростов-на-Дону Репутация: 4 Всего: 10 |
Ой, а можно пример моего невнимательного чтения книг? (Самокритику опустим.)
-------------------- Communication is critical to the job of a programmer. C. Jazdzewski. Fatherly Advice To New Programmers |
|||
|
||||
| UnrealMan |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
Контрпример можно найти прямо под носом: std::basic_ostream из стандартной библиотеки C++. Если пользователь захочет реализовать вывод информации на некоторое устройство через потоки, то он может создать новый потоковый класс, унаследовав его от std::basic_ostream (подобно тому, как это делается для basic_ofstream и basic_ostringstream). Данный базовый класс - вовсе никакой не абстрактный, и наследование реализации здесь имеет место быть. Никаких противоречий с рассуждениями, приводимыми в прочитанных мной книгах классиков, здесь нет. То, что является потоком вывода, должно быть унаследовано от std::basic_ostream. |
|||
|
||||
| Ulysses4j |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 304 Регистрация: 6.6.2007 Где: Ростов-на-Дону Репутация: 4 Всего: 10 |
Я же не говорил, что нужно запретить наследование реализации. В некоторых случаях избежать ее нельзя или трудно, это верно. Пример хороший, он демонстрирует слабость стандартной библиотеки, которая вынуждает вас наследовать реализацию, когда вы хотите наследовать интерфейс. Стандартная библиотека C++ не идеальна, как и не идеален C++, в котором понятие интерфейса не имеет воплощения в синтаксисе языка. Учтите. кстати, что все-таки есть определенная разница между стандартной библиотекой языка и сторонней библиотекой, к которой я аппелировал в посте. Классы потоков зашиты во многих интерфейсах именно потому что они входят в состав стандартных средств, в этой ситуации наследование от них для того, чтобы быть повторно использованным, а не для того, чтобы повторно использовать (© не помню кто), может быть вполне оправдано.
Еще раз прочитайте то, что вы отцитировали: я же говорю «по умолчанию». Если вы можете обосновать необходимость использования чего-то в конкретном случае, это замечательно, пользуйтесь. В том посте, да и в следующем вашем комментарии про использовании print в наследниках, я вас поддержал. Собственно, я не понимаю, в чем педмет ваших претензий ко мне. -------------------- Communication is critical to the job of a programmer. C. Jazdzewski. Fatherly Advice To New Programmers |
|||
|
||||
| UnrealMan |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
"Некоторых" - это вроде как немногочисленных? Откуда такая статистика?
О да, мы просто мечтаем унаследовать голый интерфейс, а всё форматирование, контроль за состоянием и т.д. реализовать с нуля ручками Не осилил разницу. Стандартная библиотека, или нестандартная, она может предоставлять некий базовый функционал, который пользователю может быть позволено расширять при помощи наследования, а не только использовать как часть чего-то. |
|||
|
||||
| Ulysses4j |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 304 Регистрация: 6.6.2007 Где: Ростов-на-Дону Репутация: 4 Всего: 10 |
От друзей, зарабатывающих на жизнь программированием, и из книжек.
Нет, не мечтаем. Для этого мы мечтаем использовать публичный интерфейс классов. Я так понял, что вы хотите наследоваться от basic_ostream в вашем примере, чтобы ваш класс мог использоваться там, где уже используется ostream, то есть — много где(здесь возникает аргумент о том, что стандартная библиотека отличается от обыкновенной — своей распространенностью; надеюсь, больше повторять не придется). Если вы хотели использовать какие-то protected-члены ostream, приведите, пожалуйста, пример, какие. Большая часть классов стандартной библиотеки не предназначена для наследования реализации, там никаких особо продуманных protected-интерфейсов нет, так что я с интересом бы послушал, что вам там приглянулось... -------------------- Communication is critical to the job of a programmer. C. Jazdzewski. Fatherly Advice To New Programmers |
||||
|
|||||
| NDQuattro |
|
||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 91 Регистрация: 18.7.2008 Где: Украина Репутация: нет Всего: нет |
Люди, скажите плз может ли такому определению функции
|
||||
|
|||||
| JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
NDQuattro, создавай отдельную тему!
|
|||
|
||||
| NDQuattro |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 91 Регистрация: 18.7.2008 Где: Украина Репутация: нет Всего: нет |
ок, просто ради такой мелочи форум мусорить не хотелось что то))
|
|||
|
||||
| Annihilator |
|
|||
![]() bytegrinder ![]() ![]() Профиль Группа: Участник Сообщений: 493 Регистрация: 21.11.2006 Где: Омск Репутация: 1 Всего: 3 |
Какие проблемы? Читай книги и не надо будет мусорить! (сорри -------------------- Если вы не можете сделать хоpошyю пpогpаммy, сделайте, чтобы она по кpайней меpе выглядела хоpошо |
|||
|
||||
| UnrealMan |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
Этих друзей, видимо, сотни, каждый из которых программирует в своей уникальной предметной области и притом лично сообщил тебе статистические данные своей работы? Что-то с трудом верится. А иначе это получается не очень репрезентативно. Это уже обнадёживает, правда не хватает немного конкретики (автор и название хотя бы одной из этих книг, глава, пункт, абзац). По-моему, совершенно очевидно, зачем нужно это наследование. Во-первых, basic_ostream берёт на себя много рутинной работы, во-вторых, классу, переопределяющему операцию вывода <<, нет необходимости различать, в какой именно поток будут выводить информацию, будь это cout, объект типа ofstream, объект типа ostringstream или объект типа MyOStream - с каждым видом потока можно работать единообразно.
Я не понимаю, каким боком распространённость в данном плане на что-либо влияет. |
|||
|
||||
| Ulysses4j |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 304 Регистрация: 6.6.2007 Где: Ростов-на-Дону Репутация: 4 Всего: 10 |
Так, похоже, из того, что я писал выше, вы осили процентов 20. Я считаю такой кпд слишком низким для нашей увлекательной беседы, так что засим разрешите откланиться.
-------------------- Communication is critical to the job of a programmer. C. Jazdzewski. Fatherly Advice To New Programmers |
|||
|
||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |