![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
borisbn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 22 Всего: 135 |
Не раз слышал, что наследоваться от STL-классов - не есть хорошо, однако доходчивого объяснения с конкретными примерами не видел ( я не говорю, что их нет - просто не видел
![]() Например, что плохого будет, если я наследуюсь от deque и добавлю туда некоторый функционал
Спасибо за конкретные объяснения. Хотя... за любые - тоже спасибо ![]() -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
|||
|
||||
baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
именно в этих функциях ничего страшного нет: они бесполезны, т.к. не расширяют семантику класса.
а как только захочется создать действительно специализированную версию контейнера (путем наследования), начнутся проблемы: стандартные контейнеры не являются абстрактными классами с точки зрения языка: виртуальные функции использовать нельзя (деструктор не виртуальный), и функции доступа не виртуальные с другой стороны, стандартные контейнеры являются АТД, и в этом смысле их расширять не требуется. с третьей: если, скажем, нужно создать стек на основе списка, заимствуя при этом часть функций, технически удобно использовать наследование, но - закрытое. т.е. применить прием С++, не относящийся к ООП. еще пример: паттерны типа Facade и Adapter(Wrapper) решаются путем агрегирования или закрытого наследования, а полученный класс также не предназначен для наследования Добавлено через 6 минут и 7 секунд тут главное: класс не предназначен для наследования, если его деструктор не виртуальный. у контейнеров stl так и есть авторы stl не рассчитывали, что кто-то будет наследовать. получается то же самое, как забивать гвозди разводным ключом: вроде ниче страшного, но как-то непрофессионально. а много гвоздей - еще и неэффективно Это сообщение отредактировал(а) baldina - 17.2.2011, 18:49 |
|||
|
||||
azesmcar |
|
||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
borisbn
Давай подумаем: класс deque не предназначен для наследования, значит
Да, но зачем это нужно? Все, что можно написать на основе public интерфейса, может быть написано вне класса. std::string известен, как плохо спроектированный класс потому, что в нем слишком много ненужных функций, которые могли вполне быть внешними. Например функция empty() вполне могла быть реализована вот так
и работать для любого контейнера. Интерфейс класса должен предоставлять необходимый минимум, а не все, что может понадобиться пользователю.
Плохого ничего не будет, просто наследования надо избегать, если оно не нужно. Это сообщение отредактировал(а) azesmcar - 17.2.2011, 19:01 |
||||
|
|||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
этим, хотя фактически и не нарушаете финальность класса, создаете себе ряд проблем... 1. функции принимающие вашу деку, не будут принимать стандартную 2. пр замене контейнера, на альтернативный его придется также наследовать... 3. запутывание стороннего программиста лишней сущностью 4... всех этих и многих других проблем не будет, если вместо наследования, вы будете использовать свободные функции.. ![]() Добавлено через 2 минуты и 28 секунд кстати приведенный пример отношения к вопросу "почему не желательно наследоваться от стл-контейнеров?"фактически не имеет.. и подобное расширение плохо совсем по другим причинам.. о некоторых из которых уже упомянуто выше.. |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
ага, где то было, тоже не помню где именно..
Это сообщение отредактировал(а) mes - 17.2.2011, 19:28 |
|||
|
||||
azesmcar |
|
||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Ну тогда и об остальном поговорим ![]() Функция подобная функции take_front нарушает принцип одна функция - одна задача. Далее как следствие №1
№2
код №1 и №2 НЕ эквивалентны. Хотя делают они по сути одно и тоже, но здесь есть один маленький нюанс. При возвращении T по значению вызывается копирующий конструктор, который может сгенерировать исключение. В коде №1 мы потеряем элемент, во втором коде - нет. Хотя такой вариант конечно необходим, если нужно сделать операцию атомарной. Это сообщение отредактировал(а) azesmcar - 17.2.2011, 19:43 |
||||
|
|||||
borisbn |
|
||||||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 22 Всего: 135 |
может. бесспорно. однако может и должно - разные вещи. помему всё-таки должно ?
мягко говоря не очень понимаю почему. Мне например очень нравится Qt. Там этот принцип явно не соблюдается
почему??? чевойта © Интерны? да, новые функции не будут видны, но функционал deque, как базового класса - будет Мейерс, ессно, авторитет, однако, я должен не принять, а понять ![]() Добавлено через 7 минут и 15 секунд кстати о Qt, есть там хороший класс QDir. У него есть ф-ция entryList (или как-то так). В возвращаемом списке - имена файлов или подкаталогов из каталога, который "обслуживает" этот самый QDir. Но... они все относительные, поэтому, чтобы получить список файлов с полными именами можно либо написать свободную ф-цию
либо наследоваться от QDir и добавить ф-цию
объясните, пожалуйста, чем первый вариант лучше второго ? -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
||||||||||
|
|||||||||||
azesmcar |
|
||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
потому-что свободные функции легче сделать общими. Я привел пример с функцией empty(), которая написана в каждом контейнере, хотя могла быть написана всего один раз в виде свободной функции.
см. выше ![]() я не говорю, что библиотека не должна предоставлять удобных возможностей, я говорю о том, что класс не должен походить на кучу функций. Класс дает пользователю интерфейс, чтобы тот мог менять его состояние, этого достаточно. Остальное можно вынести из класса. Интересный вопрос. Зачем надо избегать использовать то, что не нужно... ![]() Ну вообще это зависимости, их надо избегать. Наследование - тесная связь, самая тесная после дружбы. Посмотри в книге "Новые сложные задачи на C++ Герба Саттера", глава 37, Ослабленная монолитность std::string. Это сообщение отредактировал(а) azesmcar - 17.2.2011, 20:49 |
||||
|
|||||
borisbn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 22 Всего: 135 |
azesmcar, я правильно понимаю, что единственным аргументом (во всяком случае чётко сформулированным) является наличие тесной связи (зависимостей), которые 1) замедляют компиляцию 2) принуждают тянуть за собой набор h-ников
и всё ? в принципе - тоже аргумент, но IMHO не решающий -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Нет, я же написал, что в таком случае возможно придется (сейчас или в будущем) писать много дубликатов, mes привел еще аргументы. Нет такой заповеди "не наследуй". Надо так надо, но зачем зря сваливать на свою голову проблемы? Посмотри в книгу, о которой я писал. Там 4 главы, всего не перескажешь. ![]() Это сообщение отредактировал(а) azesmcar - 17.2.2011, 20:54 |
|||
|
||||
borisbn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 22 Всего: 135 |
azesmcar, то, что оно не нужно, сказали вы, соответственно ответ на вопрос почему - потому, что не нужно - рекурсия ![]() Добавлено через 1 минуту и 49 секунд читал и не раз, но, т.к. не нашёл там понятных (для меня, ессно) объяснений, поэтому и обратился на форум -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
ну...не нужно, потому-что это ничего не дает. ![]() хорошо, вот Вы скажите (я не знаю Qt, потому давайте вернемся к STL ![]() Расширение класса по средствам наследования vs свободная функция. Ваш выбор (аргументированный естественно). Это сообщение отредактировал(а) azesmcar - 17.2.2011, 20:58 |
|||
|
||||
borisbn |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 22 Всего: 135 |
абсолютно ничем, однако в нескольких источниках ( azesmcar, Мейерс ![]()
![]() -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
||||
|
|||||
azesmcar |
|
||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
borisbn
Ну..может молодой специалист решил реализовать STL, а функцию empty забыл..например в нашей компании один мужик (видимо очень важный, так-как его до моего появления все еще не уволили) решил, что компании позарез необходим свой класс string, так-как STL-овский неудачен..в нем видите ли мало функций ![]() так у нас появился свой класс string (наследник std::string естественно, с нуля написать у него бы мозгов не хватило), в котором были функции (приготовьтесь, это не шутка)
в общем..не отвлекаемся....
хорошо, говорим в контексте того же примера. наследовать придется все классы, в каждом писать ту же самую функцию, в то время как в виде свободной функции придется написать всего одну и наследовать тоже ничего не надо. Плюсы избавляемся от зависимостей пишем меньше кода избавляем себя от необходимости дублировать функцию избавляем себя от UB при возможным удалением наследника через указатель базового ... и так далее. и Вы можете сказать, что свободная функция не лучше? |
||||
|
|||||
borisbn |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: 22 Всего: 135 |
получается как-то, что я отстаиваю наследование, хотя это не так. я просто хочу разобраться...
azesmcar, в вашем примере чем такое
лучше, чем
честно говоря, перечитал - из пальца высосано, но....... то ли пример - не очень, то ли я уже спать хочу ![]()
жесть... не верю ![]() -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
||||||
|
|||||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |