Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> наследование от классов STL 
V
    Опции темы
borisbn
Дата 17.2.2011, 18:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Не раз слышал, что наследоваться от STL-классов - не есть хорошо, однако доходчивого объяснения с конкретными примерами не видел ( я не говорю, что их нет - просто не видел smile ). Все объяснения сводятся к тому, что они (STL-классы) не предназначены для этого, но, согласитесь, что это - довольно общее объяснение, и не говорит почему же именно они не предназначены.
Например, что плохого будет, если я наследуюсь от deque и добавлю туда некоторый функционал
Код

T MyDeque::take_front() {
  // здесь можно ещё добавить scoped_locker
  T res = front();
  pop_front();
  return res;
}

T MyDeque::take_back() {
  T res = back();
  pop_back();
  return res;
}

Спасибо за конкретные объяснения. Хотя... за любые - тоже спасибо smile


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
baldina
Дата 17.2.2011, 18:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



именно в этих функциях ничего страшного нет: они бесполезны, т.к. не расширяют семантику класса.
а как только захочется создать действительно специализированную версию контейнера (путем наследования), начнутся проблемы: стандартные контейнеры не являются абстрактными классами с точки зрения языка: виртуальные функции использовать нельзя (деструктор не виртуальный), и функции доступа не виртуальные
с другой стороны, стандартные контейнеры являются АТД, и в этом смысле их расширять не требуется.
с третьей: если, скажем, нужно создать стек на основе списка, заимствуя при этом часть функций, технически удобно использовать наследование, но - закрытое. т.е. применить прием С++, не относящийся к ООП. 
еще пример: паттерны типа Facade и Adapter(Wrapper) решаются путем агрегирования или закрытого наследования, а полученный класс также не предназначен для наследования

Добавлено через 6 минут и 7 секунд
тут главное: класс не предназначен для наследования, если его деструктор не виртуальный.
у контейнеров stl так и есть
авторы stl не рассчитывали, что кто-то будет наследовать. получается то же самое, как забивать гвозди разводным ключом: вроде ниче страшного, но как-то непрофессионально. а много гвоздей - еще и неэффективно

Это сообщение отредактировал(а) baldina - 17.2.2011, 18:49
PM MAIL   Вверх
azesmcar
Дата 17.2.2011, 18:58 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



borisbn

Давай подумаем: класс deque не предназначен для наследования, значит
  • у него нет виртуального деструктора
  • у него нет виртуальных функций, которые можно переопределить
  • он не предоставляет protected интерфейса
что в таком случае дает нам наследование? возможность добавления новых функций на основе public интерфейса этого класса?
Да, но зачем это нужно? Все, что можно написать на основе public интерфейса, может быть написано вне класса. std::string известен, как плохо спроектированный класс потому, что в нем слишком много ненужных функций, которые могли вполне быть внешними.
Например функция empty() вполне могла быть реализована вот так
Код

template <typename T>
bool empty(const T& c) {
    return c.begin() == c.end();
}

и работать для любого контейнера. Интерфейс класса должен предоставлять необходимый минимум, а не все, что может понадобиться пользователю.
Цитата(borisbn @  17.2.2011,  18:16 Найти цитируемый пост)
Например, что плохого будет, если я наследуюсь от deque и добавлю туда некоторый функционал

Плохого ничего не будет, просто наследования надо избегать, если оно не нужно.

Это сообщение отредактировал(а) azesmcar - 17.2.2011, 19:01
PM   Вверх
mes
Дата 17.2.2011, 19:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(borisbn @  17.2.2011,  15:58 Найти цитируемый пост)
а почему, если я добавлю в deque такие ф-ции, я "нарушу логическую полноценность" 

этим, хотя фактически и не нарушаете финальность класса, создаете себе ряд проблем... 
1. функции принимающие вашу деку, не будут принимать стандартную
2. пр замене контейнера, на альтернативный его придется также наследовать... 
3. запутывание стороннего программиста лишней сущностью
4...
всех этих и многих других проблем не будет, если вместо наследования, вы будете использовать свободные функции.. 
smile

Добавлено через 2 минуты и 28 секунд
Цитата(borisbn @  17.2.2011,  17:16 Найти цитируемый пост)
если я наследуюсь от deque 

кстати приведенный пример отношения к вопросу "почему не желательно наследоваться от стл-контейнеров?"фактически не имеет.. 
и подобное расширение плохо совсем по другим причинам.. о некоторых из которых уже упомянуто выше.. 



--------------------
PM MAIL WWW   Вверх
mes
Дата 17.2.2011, 19:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(baldina @  17.2.2011,  17:38 Найти цитируемый пост)
 а мне казалось я где-то видел закрытое наследование... 

ага, где то было, тоже не помню где именно..


Цитата("Эффективный C++" @  Мейерс)

    Продумывайте подход к использованию закрытого наследования
  • Закрытое наследование означает «реализован посредством». Обычно этот вариант хуже композиции, но все же приобретает смысл, когда производный класс нуждается в доступе к защищенным членам базового класса или должен переопределять унаследованные виртуальные функции.
  • В отличие от композиции, закрытое наследование позволяет проводить оптимизацию пустого базового класса. Это может оказаться важным для разработчиков библиотек, которые стремятся минимизировать размеры объектов.



Это сообщение отредактировал(а) mes - 17.2.2011, 19:28


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 17.2.2011, 19:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(mes @  17.2.2011,  19:07 Найти цитируемый пост)
кстати приведенный пример отношения к вопросу "почему не желательно наследоваться от стл-контейнеров?"фактически не имеет.. 
и подобное расширение плохо совсем по другим причинам.. о некоторых из которых уже упомянуто выше.. 


Ну тогда и об остальном поговорим smile 

Функция подобная функции take_front нарушает принцип одна функция - одна задача.
Далее как следствие
№1
Код

T res = front();
pop_front();
// do something with res

№2
Код

T res = take_front();
// do something with res

код №1 и №2 НЕ эквивалентны. Хотя делают они по сути одно и тоже, но здесь есть один маленький нюанс.
При возвращении T по значению вызывается копирующий конструктор, который может сгенерировать исключение. В коде №1 мы потеряем элемент, во втором коде - нет. Хотя такой вариант конечно необходим, если нужно сделать операцию атомарной.

Это сообщение отредактировал(а) azesmcar - 17.2.2011, 19:43
PM   Вверх
borisbn
Дата 17.2.2011, 20:37 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(azesmcar @  17.2.2011,  18:58 Найти цитируемый пост)
Все, что можно написать на основе public интерфейса, может быть написано вне класса.

может. бесспорно. однако может и должно - разные вещи. помему всё-таки должно ?
Цитата(azesmcar @  17.2.2011,  18:58 Найти цитируемый пост)
Интерфейс класса должен предоставлять необходимый минимум, а не все, что может понадобиться пользователю.

мягко говоря не очень понимаю почему. Мне например очень нравится Qt. Там этот принцип явно не соблюдается

Цитата(azesmcar @  17.2.2011,  18:58 Найти цитируемый пост)
Плохого ничего не будет, просто наследования надо избегать, если оно не нужно.

почему???

Цитата(mes @  17.2.2011,  19:07 Найти цитируемый пост)
функции принимающие вашу деку, не будут принимать стандартную

чевойта © Интерны? да, новые функции не будут видны, но функционал deque, как базового класса - будет

Цитата(mes @  17.2.2011,  19:26 Найти цитируемый пост)
("Эффективный C++" @  Мейерс)

Мейерс, ессно, авторитет, однако, я должен не принять, а понять smile

Добавлено через 7 минут и 15 секунд
кстати о Qt, есть там хороший класс QDir. У него есть ф-ция entryList (или как-то так). В возвращаемом списке - имена файлов или подкаталогов из каталога, который "обслуживает" этот самый QDir. Но... они все относительные, поэтому, чтобы получить список файлов с полными именами можно либо написать свободную ф-цию
Код

QStringList fullEntryList( const QDir & d, const QString & mask ) {
  QStringList sl = d.entryList( mask );
  QStringList res;
  foreach ( const QString & f, sl ) {
    res << d.dir() + "/" + f;
  }
  return res;
}

либо наследоваться от QDir и добавить ф-цию
Код

QStringList FullDir::entryListFull( const QString & mask ) {
... ну и т.д.
}

объясните, пожалуйста, чем первый вариант лучше второго ?


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
azesmcar
Дата 17.2.2011, 20:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(borisbn @  17.2.2011,  20:37 Найти цитируемый пост)
может. бесспорно. однако может и должно - разные вещи. помему всё-таки должно ?

потому-что свободные функции легче сделать общими. Я привел пример с функцией empty(), которая написана в каждом контейнере, хотя могла быть написана всего один раз в виде свободной функции.

Цитата(borisbn @  17.2.2011,  20:37 Найти цитируемый пост)
мягко говоря не очень понимаю почему. Мне например очень нравится Qt. Там этот принцип явно не соблюдается

см. выше smile 
я не говорю, что библиотека не должна предоставлять удобных возможностей, я говорю о том, что класс не должен походить на кучу функций. Класс дает пользователю интерфейс, чтобы тот мог менять его состояние, этого достаточно. Остальное можно вынести из класса.

Цитата(borisbn @  17.2.2011,  20:37 Найти цитируемый пост)
почему???

Интересный вопрос.
Цитата(azesmcar @  17.2.2011,  18:58 Найти цитируемый пост)
наследования надо избегать, если оно не нужно

Зачем надо избегать использовать то, что не нужно... smile 
Ну вообще это зависимости, их надо избегать. Наследование - тесная связь, самая тесная после дружбы.

Посмотри в книге "Новые сложные задачи на C++ Герба Саттера", глава 37, Ослабленная монолитность std::string.


Это сообщение отредактировал(а) azesmcar - 17.2.2011, 20:49
PM   Вверх
borisbn
Дата 17.2.2011, 20:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



azesmcar, я правильно понимаю, что единственным аргументом (во всяком случае чётко сформулированным) является наличие тесной связи (зависимостей), которые 1) замедляют компиляцию 2) принуждают тянуть за собой набор h-ников
и всё ?

в принципе - тоже аргумент, но IMHO не решающий


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
azesmcar
Дата 17.2.2011, 20:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(borisbn @  17.2.2011,  20:50 Найти цитируемый пост)
azesmcar, я правильно понимаю, что единственным аргументом (во всяком случае чётко сформулированным) является наличие тесной связи (зависимостей), которые 1) замедляют компиляцию 2) принуждают тянуть за собой набор h-ников
и всё ?

Нет, я же написал, что в таком случае возможно придется (сейчас или в будущем) писать много дубликатов, mes привел еще аргументы. Нет такой заповеди "не наследуй". Надо так надо, но зачем зря сваливать на свою голову проблемы?

Посмотри в книгу, о которой я писал. Там 4 главы, всего не перескажешь. smile 

Это сообщение отредактировал(а) azesmcar - 17.2.2011, 20:54
PM   Вверх
borisbn
Дата 17.2.2011, 20:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(azesmcar @  17.2.2011,  20:45 Найти цитируемый пост)

Интересный вопрос.

наследования надо избегать, если оно не нужно

Зачем надо избегать использовать то, что не нужно...


azesmcar, то, что оно не нужно, сказали вы, соответственно ответ на вопрос почему - потому, что не нужно - рекурсия smile IMHO

Добавлено через 1 минуту и 49 секунд
Цитата(azesmcar @  17.2.2011,  20:52 Найти цитируемый пост)
Посмотри в книгу, о которой я писал.

читал и не раз, но, т.к. не нашёл там понятных (для меня, ессно) объяснений, поэтому и обратился на форум


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
azesmcar
Дата 17.2.2011, 20:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(borisbn @  17.2.2011,  20:55 Найти цитируемый пост)
azesmcar, то, что оно не нужно, сказали вы, соответственно ответ на вопрос почему - потому, что не нужно - рекурсия  IMHO 

ну...не нужно, потому-что это ничего не дает. smile 

хорошо, вот Вы скажите (я не знаю Qt, потому давайте вернемся к STL smile ) чем функция empty() в виде метода лучше, чем в виде свободной функции? Допустим у нас есть классы vector, list и string и какой-то молодой специалист забыл добавить в них функцию empty(). Ваши действия.

Расширение класса по средствам наследования vs свободная функция.

Ваш выбор (аргументированный естественно).


Это сообщение отредактировал(а) azesmcar - 17.2.2011, 20:58
PM   Вверх
borisbn
Дата 17.2.2011, 21:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(azesmcar @  17.2.2011,  20:57 Найти цитируемый пост)
чем функция empty() в виде метода лучше, чем в виде свободной функции?

абсолютно ничем, однако в нескольких источниках ( azesmcar, Мейерс smile ) утверждается, что свободные ф-ции лучше, а я и не могу понять почему... почему лучше ? почему не поставить их на одну полку ?

Цитата(azesmcar @  17.2.2011,  20:57 Найти цитируемый пост)
какой-то молодой специалист забыл добавить в них функцию empty()

Цитата(azesmcar @  17.2.2011,  20:57 Найти цитируемый пост)
давайте вернемся к STL 

 smile 



--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
azesmcar
Дата 17.2.2011, 21:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



borisbn

Ну..может молодой специалист решил реализовать STL, а функцию empty забыл..например в нашей компании один мужик (видимо очень важный, так-как его до моего появления все еще не уволили) решил, что компании позарез необходим свой класс string, так-как STL-овский неудачен..в нем видите ли мало функций smile 

так у нас появился свой класс string (наследник std::string естественно, с нуля написать у него бы мозгов не хватило), в котором были функции (приготовьтесь, это не шутка)
Код

bool mkdir() const; // создает директорию с именем из строки *this
static void sleep(int seconds); // да да..обычный sleep, слава богу хоть static
// ... и так далее в том же стиле

в общем..не отвлекаемся....

Цитата(borisbn @  17.2.2011,  21:03 Найти цитируемый пост)
абсолютно ничем, однако в нескольких источниках ( azesmcar, Мейерс  ) утверждается, что свободные ф-ции лучше

хорошо, говорим в контексте того же примера. наследовать придется все классы, в каждом писать ту же самую функцию, в то время как в виде свободной функции придется написать всего одну и наследовать тоже ничего не надо.
Плюсы
избавляемся от зависимостей
пишем меньше кода
избавляем себя от необходимости дублировать функцию
избавляем себя от UB при возможным удалением наследника через указатель базового
... и так далее.

и Вы можете сказать, что свободная функция не лучше?
PM   Вверх
borisbn
Дата 17.2.2011, 21:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



получается как-то, что я отстаиваю наследование, хотя это не так. я просто хочу разобраться...
azesmcar, в вашем примере чем такое
Код

template< class T >
class ContainerWithEmty : public T {
public:
bool empty() const {
  return begin() == end();
}
};

лучше, чем
Код

template <typename T>
bool empty(const T& c) {
    return c.begin() == c.end();
}


честно говоря, перечитал - из пальца высосано, но....... то ли пример - не очень, то ли я уже спать хочу smile





Цитата

bool mkdir() const; // создает директорию с именем из строки *this
static void sleep(int seconds);


жесть... не верю smile


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
azesmcar
Дата 17.2.2011, 21:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(borisbn @  17.2.2011,  21:15 Найти цитируемый пост)
azesmcar, в вашем примере чем такое


Цитата(borisbn @  17.2.2011,  21:15 Найти цитируемый пост)
лучше, чем

Конкретно это я писал в ответ на вопрос, почему свободные функции предпочтительнее методов и чем плохи монолитные классы. 
Давайте углубимся в детали. Программист написал функцию метод, работающую для контейнера vector. Функция работает используя итераторы. Теперь мне тоже необходима эта функция и мне придется дублировать код, хотя этот код мог быть написан в виде свободной функции и использоваться для каждого контейнера (хороший пример алгоритмы STL).

конкретно в приведенном коде эффект тот же, но здесь Вы получает букет проблем, связанных с наследованием не получив ничего взамен. В чем смысл?

Добавлено через 1 минуту и 31 секунду
Цитата(borisbn @  17.2.2011,  21:15 Найти цитируемый пост)
жесть... не верю  

я бы показал, там еще много смешного, но я оттуда 4 года назад уволился smile 
причем писал не индус какой нибудь, а американец, с высшим американским образованием. smile 
PM   Вверх
mes
Дата 17.2.2011, 22:10 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(borisbn @  17.2.2011,  19:50 Найти цитируемый пост)
 является наличие тесной связи (зависимостей), которые 1) замедляют компиляцию 2) принуждают тянуть за собой набор h-ников
и всё ?

Вы явно упускаете все, что Вам уже не одним постом пытаются объяснить..
скорость компиляции и тяга это все все мелкие проблемы..  самая главная проблема в напряжении мозга наличием лишних сущностей.. 
все остальное ерунда.. 
если в программа основанна на уже упомянутом классе string, то пусть будет что угодно, хоть "format c: "
но если Вы хотите строить из удобных кирпичиков, которые не нужно три дня шлифовать, прежде чем состыковать, 
и иметь такую стену, в которой при замене кирпича на другой аналогичный не нужно заново перебирать всю постройку, то тогда думаю стоит обратить более пристальное внимание на советы, приведенные выше... 



--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 17.2.2011, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Мы тут говорим о двух моментах одновременно и все запутывается. Давайте разберемся.

имеем два утверждения.

1. класс не должен быть монолитным и должен предоставлять минимально возможный интерфейс. Остальные функции, которые можно написать на основе public интерфейса класса должны быть свободными.
2. не надо наследовать класс, если это НЕ необходимо.

Первый пункт возник из за приведенного ТС примера. По первому пункту все есть еще разногласия?

Это сообщение отредактировал(а) azesmcar - 17.2.2011, 22:35
PM   Вверх
alexvs11
Дата 17.2.2011, 22:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


hell is here
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 21.8.2010

Репутация: 6
Всего: 10



azesmcar, первый вопрос менее очевидный
PM MAIL   Вверх
mes
Дата 17.2.2011, 23:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(borisbn @  17.2.2011,  20:15 Найти цитируемый пост)
в вашем примере чем такое:
Код

bool empty() const {
  return begin() == end();
}

лучше, чем
Код

bool empty(const T& c) {
    return c.begin() == c.end();
}



советую поразмышлять, чем отличается свободная функция swap от одноименного члена.. где лежат их области применения.. 
и почему одна не может заменить другую..
smile



--------------------
PM MAIL WWW   Вверх
maxim1000
Дата 17.2.2011, 23:55 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 17
Всего: 110



попробую ещё с двух сторон взгляд предоставить
(вообще-то думал с одной, но пока писал, увидел вторую smile)

1. с точки зрения пользователя дополнительной функциональности
Код, написанный в take_front, по сути, подходит для любого deque, однако он требует чтобы объект был именно типа MyDeque. Как объяснить пользователю (другому программисту) какими причинами руководствовался разработчик, когда добавлял такое ограничение? Чего ради?

2. с точки зрения разработчика дополнительной функциональности
Наследование, как способ расширения функциональности, не очень хорошо масштабируется.

Например, есть у нас std::deque.
Класс хороший, но кому-то не нравится, что там нет функции remove_first_half_of_elements. Решение простое - наследуем класс, добавляем метод.

Другому программисту не нравится, что нет функции duplicate_all_elements. Решение простое - наследуем класс, добавляем метод.

Третьему программисту захотелось и того, и того. Решение очевидное - множественное наследование (ну не писать же код заново). Сразу же выясняется, что наследование от std::deque не виртуальное, нужно править код.

Каждая новая комбинация желаемой функциональности - новый класс (т.е. количество классов экспоненциально растёт). Альтернатива - создать один класс, в который впихнуть все расширения. Теперь у пользователей нет возможности не зависеть от новой функциональности, которая (потенциально) тянет за собой кучу других ненужных зависимостей...

Сравним с внешними функциями: хочешь функцию - подключай h-файл и пользуйся. Тянет какие-то зависимости - подключай и тягай с собой дополнительные библиотеки. Но только для той функциональности, которая тебе реально нужна. Не больше. Красота smile

Это сообщение отредактировал(а) maxim1000 - 17.2.2011, 23:59


--------------------
qqq
PM WWW   Вверх
alexvs11
Дата 18.2.2011, 00:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


hell is here
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 21.8.2010

Репутация: 6
Всего: 10



maxim1000, да, это похоже на правду жизни
в некоторых проектах постоянное добавление функциональности приводит к появлению глубокой иерархией в этак > 10 классов, перемежая с множественным наследованием ( обязательно где-нибудь встретится повторное наследование smile )
этакий архитектурный коллапс

Это сообщение отредактировал(а) alexvs11 - 18.2.2011, 00:11
PM MAIL   Вверх
volatile
Дата 18.2.2011, 01:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(borisbn @  17.2.2011,  18:16 Найти цитируемый пост)
Не раз слышал, что наследоваться от STL-классов - не есть хорошо

Ну и темка разрослась, по неосторожно брошенному мной вчера слову.
Спасибо всем, почитал с удовольствием.
А вообще, мое мнение такое. Если программер точно знает что делает, то на здоровье! Страуструп, например, где-то наследуется в своей книге от вектора. 
Ну ему можно (так же как и всем кто досконально понимает, что делает).
Сам я от стл никогда не наследуюсь. Так как далеко мне еще до глубокого понимания механизмов...
А вот goto, например, иногда применяю. И плевать, что там подумают. Есть случаи когда это оправдано.
так-же и здесь, вероятно есть случаи когда стоит нарушить правила. 
Но до этого нужно сначала дорости.

PM MAIL   Вверх
azesmcar
Дата 18.2.2011, 06:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(volatile @  18.2.2011,  01:34 Найти цитируемый пост)
Страуструп, например, где-то наследуется в своей книге от вектора.

То было private наследование.
Цитата(volatile @  18.2.2011,  01:34 Найти цитируемый пост)
А вот goto, например, иногда применяю. И плевать, что там подумают. Есть случаи когда это оправдано.

Один раз писал алгоритм и казалось вот он тот случай, мне нужен goto! Порадовался, но сделал с помощью switchsmile 
Код

template <typename M1, typename M2, typename M3, typename M4, typename M5>
bool try_lock_without_deadlock(M1& m1, M2& m2, M3& m3, M4& m4, M5& m5)
{
    int locked = 0;
    switch (locked)
    {
    case 0: if (!m1.try_lock()) break; ++locked;
    case 1: if (!m2.try_lock()) break; ++locked;
    case 2: if (!m3.try_lock()) break; ++locked;
    case 3: if (!m4.try_lock()) break; ++locked;
    case 4: if (!m5.try_lock()) break; ++locked;
    }
    switch (locked)
    {
    case 5: return true;
    case 4: m4.unlock();
    case 3: m3.unlock();
    case 2: m2.unlock();
    case 1: m1.unlock();
    }
    return false;
}


Цитата(maxim1000 @  17.2.2011,  23:55 Найти цитируемый пост)
Сравним с внешними функциями: хочешь функцию - подключай h-файл и пользуйся. Тянет какие-то зависимости - подключай и тягай с собой дополнительные библиотеки. Но только для той функциональности, которая тебе реально нужна. Не больше. Красота 

причем разница только в синтаксисе вызова
Код

function(obj);

и
Код

obj.function();



Это сообщение отредактировал(а) azesmcar - 18.2.2011, 06:13
PM   Вверх
borisbn
Дата 18.2.2011, 09:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



ok, насколько я понял, если пишешь не универсальную библиотеку, а так... программку однодневку, если в принципе не представляешь, как этот код можно повторно использовать в другом месте, и если точно знаешь, что делаешь, то в наследовании для расширения функционала нет ничего криминального, что действительно повлияет на работу программы, и даже на её поддержку. Во всех остальных случаях целесообразно писать свободные функции.

Цитата(mes @  17.2.2011,  22:10 Найти цитируемый пост)
но если Вы хотите строить из удобных кирпичиков, которые не нужно три дня шлифовать, прежде чем состыковать, и иметь такую стену, в которой при замене кирпича на другой аналогичный не нужно заново перебирать всю постройку, то тогда думаю стоит обратить более пристальное внимание на советы, приведенные выше... 

это то ясно, не первый раз замужем smile
Понимаете, я поднял тему вовсе не потому, что защищаю наследование от STL-классов, а потому, что внятного объяснения почему это плохо не видел. Впрочем также, как и использование goto, что не значит, что я буду говорить направо и налево: "использование goto - хорошо".

ok, всем большущее спасибо. закрываю "для галочки", но мониторить буду, так, что, если есть ещё мысли/идеи - welcome smile


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
mes
Дата 18.2.2011, 10:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(borisbn @  18.2.2011,  08:53 Найти цитируемый пост)
 наследование от STL-классов, а потому, что внятного объяснения почему это плохо не видел. 

это не плохо  smile , просто "любой" другой вариант в общем случае лучше  smile

Добавлено через 39 секунд
а если есть лучшее, то зачем создавать себе лишние неудобства ?.. smile

Добавлено через 1 минуту и 32 секунды
а так любое решение - плохое, но из двух зол принято выбирать меньшее © smile

Добавлено через 3 минуты и 13 секунд
в общем при открытом наследовании от стл контейнера, его ценность как класса падает.. 
а при использовании свободной функции, ценность самого класса не изменяется, а появляется еще возможно ценная функция smile




--------------------
PM MAIL WWW   Вверх
volatile
Дата 18.2.2011, 23:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



 smile 
Цитата(azesmcar @  18.2.2011,  06:10 Найти цитируемый пост)
Один раз писал алгоритм и казалось вот он тот случай, мне нужен goto! Порадовался, но сделал с помощью switch

Да, но смысл явно здесь затуманен. Первый свитч вообще не понятно зачем. Некоторые для этой же цели любят применять
do{...; break; ...}while(0); лишь бы не применять goto. Зачем такие ухищрения? С goto было бы ясней. smile. А чем ясней, тем лучше.

PM MAIL   Вверх
mes
Дата 18.2.2011, 23:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(volatile @  18.2.2011,  22:49 Найти цитируемый пост)
С goto было бы ясней

volatile, если приведете пример с goto, который будет структурно ясней, "заработаете" +1 в репу  smile 



--------------------
PM MAIL WWW   Вверх
volatile
Дата 19.2.2011, 01:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(mes @  18.2.2011,  23:56 Найти цитируемый пост)
если приведете пример с goto, который будет структурно ясней

Ну, собственно само напрашивается...
(просто убрал первый свитч, с ненужными case'ми который, имхо, и затуманивает дело.)
Код

template <typename M1, typename M2, typename M3, typename M4, typename M5>
bool try_lock_without_deadlock(M1& m1, M2& m2, M3& m3, M4& m4, M5& m5)
{
    int locked = 0;
    if (!m1.try_lock()) goto exit; ++locked;
    if (!m2.try_lock()) goto exit; ++locked;
    if (!m3.try_lock()) goto exit; ++locked;
    if (!m4.try_lock()) goto exit; ++locked;
    if (!m5.try_lock()) goto exit; ++locked;

exit:
    switch (locked)
    {
    case 5: return true;
    case 4: m4.unlock();
    case 3: m3.unlock();
    case 2: m2.unlock();
    case 1: m1.unlock();
    }
    return false;
}

PM MAIL   Вверх
mes
Дата 19.2.2011, 01:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(volatile @  19.2.2011,  00:09 Найти цитируемый пост)
просто убрал первый свитч, 

ну так о я могу.. ну да ладно, пусть один.. smile
но где ж обещанная ясность ? структура кода та же, а еще приходится глазами выискавать метку... smile
 smile

Цитата(volatile @  18.2.2011,  22:49 Найти цитируемый пост)
любят применять
do{...; break; ...}while(0); лишь бы не применять goto

применительно к этой задачи он, имхо, удачнее подходит, чем goto или switch..

Это сообщение отредактировал(а) mes - 19.2.2011, 01:34


--------------------
PM MAIL WWW   Вверх
volatile
Дата 19.2.2011, 02:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(mes @  19.2.2011,  01:26 Найти цитируемый пост)
структура кода та же, а еще приходится глазами выискавать метку

Ну метку заметить не трудно.  smile гораздо труднее понять зачем там свитч.
Ну да ладно... smile 
PM MAIL   Вверх
boostcoder
Дата 19.2.2011, 02:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



задавался подобным вопросом, возможно на этом форуме, не помню.. но, как результат, все равно реализую string_list и string_vector унаследовав list или vector соответственно. ничего плохого в этом нет.

Добавлено через 58 секунд
goto - да. сложно представить ситуацию, когда он нужен. в жизни такой надобности не встречал в с++.

PM WWW   Вверх
azesmcar
Дата 19.2.2011, 07:19 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



volatile
Ну вообще-то goto здесь не так напрашивался. В твоем примере goto вообще непонятно зачем нужен.
Я вот это имел ввиду.
Код

template <typename M1, typename M2, typename M3, typename M4, typename M5>
bool try_lock_without_deadlock(M1& m1, M2& m2, M3& m3, M4& m4, M5& m5)
{
    if (!m1.try_lock()) goto rollback0;
    if (!m2.try_lock()) goto rollback1;
    if (!m3.try_lock()) goto rollback2;
    if (!m4.try_lock()) goto rollback3;
    if (!m5.try_lock()) goto rollback4;
    return true;
rollback4:
    m4.unlock();
rollback3:
    m3.unlock();
rollback2:
    m2.unlock();
rollback1:
    m1.unlock();
rollback0:
    return false;
}

Хотя второй switch любой уважающий себя компилятор и преобразует в таблицу переходов, первая часть все таки имеет небольшой overhead при инкрементировании счетчика. Так-что с goto выйдет чуточку быстрее.
Несмотря на то, что я сделал через switch, я думаю это хороший пример, когда goto действительно является неплохим решением.
PM   Вверх
mes
Дата 19.2.2011, 14:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(volatile @  19.2.2011,  01:04 Найти цитируемый пост)
Ну метку заметить не трудно.   гораздо труднее понять зачем там свитч.

да дело не столько в метке, сколько в архитектурном решении, в котором гото никакой абсолютно пользы не принес, а при этом еще и мог бы добавить затруднения.. smile


--------------------
PM MAIL WWW   Вверх
alexvs11
Дата 19.2.2011, 14:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


hell is here
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 21.8.2010

Репутация: 6
Всего: 10



Цитата(boostcoder @  19.2.2011,  02:35 Найти цитируемый пост)
string_list и string_vector унаследовав list или vector соответственно. ничего плохого в этом нет.

чем это лучше будет std::list<std::string> > и std::vector<std::string> >
одновременное наследование в этом случае этож ужостъ, хотя бы по колву одинаковых методов в обоих классах

Добавлено через 1 минуту и 30 секунд
уж что угодно лучше было бы агрегировать std::list<std::string> или наследовать в новый класс
PM MAIL   Вверх
baldina
Дата 19.2.2011, 19:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



mes, goto поможет при выходе из глубоко вложенного цикла. 
того же можно достичь исключениями, но не дело использовать исключения в структурных целях
менее очевидное применение - войти в середину вложенного цикла с некоторыми не начальными значениями параметров. например, мы не закончили обработку, а потом хотим продолжить с того же места
...
Цитата(borisbn @  18.2.2011,  09:53 Найти цитируемый пост)
ok, насколько я понял, если пишешь не универсальную библиотеку, а так... программку однодневку, если в принципе не представляешь, как этот код можно повторно использовать в другом месте, и если точно знаешь, что делаешь, то в наследовании для расширения функционала нет ничего криминального, что действительно повлияет на работу программы, и даже на её поддержку. Во всех остальных случаях целесообразно писать свободные функции.

все-таки все немного глубже. 
1. если программа будет развиваться, сопровождаться и т.д., уменьшение связей (зависимостей) упростит жизнь.
2. наследование (по сравнению со свободной функцией) носит более специфический характер, т.к. не просто решает еще одну задачу, а является результатом проектных обобщений.
3. самовоспитание. если привыкнуть что-то делать правильно, меньше надо будет напрягаться в случаях, когда "делать правильно" следует обязательно
PM MAIL   Вверх
mes
Дата 19.2.2011, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(baldina @  19.2.2011,  18:01 Найти цитируемый пост)
 goto поможет при выходе из глубоко вложенного цикла. 

 smile, я в курсе.. и я не противник goto, но сторонник применения альтернативных и не "очевидных" методов..
П.С. если идут на пользу, а не просто потому что "где-то увидел что так надо"..   smile 

Цитата(baldina @  19.2.2011,  18:01 Найти цитируемый пост)
того же можно достичь исключениями, но не дело использовать исключения в структурных целях

ну это уже извращение, по воробьям из пушки.. smile

Цитата(baldina @  19.2.2011,  18:01 Найти цитируемый пост)
самовоспитание. если привыкнуть что-то делать правильно, меньше надо будет напрягаться в случаях, когда "делать правильно" следует обязательно 

 smile 

P.S. "правильно" - это значит создавать как можно меньше потенциальных проблем smile




--------------------
PM MAIL WWW   Вверх
Alexeis
Дата 20.2.2011, 15:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Цитата(baldina @  19.2.2011,  20:01 Найти цитируемый пост)
того же можно достичь исключениями, но не дело использовать исключения в структурных целях

  А я использую, причем часто генерю строковое исключение (LPCWSTR) . Удобно можно сразу текст ошибки указать. Либо исключение с кодом. На сегодняшний день это нормально. Даже lexical_cast<> генерит как результат неуспеха.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
mes
Дата 20.2.2011, 15:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Alexeis @  20.2.2011,  14:40 Найти цитируемый пост)
 А я использую, причем часто генерю строковое исключение (LPCWSTR) . Удобно можно сразу текст ошибки указать. Либо исключение с кодом. На сегодняшний день это нормально. Даже lexical_cast<> генерит как результат неуспеха. 

ммм.. только вот как связано "результат неуспеха" и "выход из вложенного цикла" ?!
 smile 




--------------------
PM MAIL WWW   Вверх
volatile
Дата 20.2.2011, 16:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(azesmcar @  19.2.2011,  07:19 Найти цитируемый пост)
volatile
Ну вообще-то goto здесь не так напрашивался. В твоем примере goto вообще непонятно зачем нужен.

azesmcar, ну первый свитч сбивает с толку просто.
Ну и mes сказал чтобы с гото было.  smile 
Я бы это вообще вот так написал.
Код

template <typename M1, typename M2, typename M3, typename M4, typename M5>
bool try_lock_without_deadlock(M1& m1, M2& m2, M3& m3, M4& m4, M5& m5)
{
   if (m1.try_lock())
   {
      if (m2.try_lock())
      {
         if (m3.try_lock())
         {
            if (m4.try_lock())
            {
               if (m5.try_lock())
                  return true;
               m4.unlock();
            }
            m3.unlock();
         }
         m2.unlock();
      }
      m1.unlock();
   }
   return false;
}

Хотя это все дело вкуса, конечно.


PM MAIL   Вверх
Alexeis
Дата 20.2.2011, 16:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



mes, ну досрочный выход из вложенного цикла это часто какой-то результат. Положительный или отрицательный. Исключение это не обязательно крах. Это вполне может быть отрицательный результат проверки. Иногда удобно положительный результат выводить как исключение. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
azesmcar
Дата 20.2.2011, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(volatile @  20.2.2011,  16:02 Найти цитируемый пост)
Я бы это вообще вот так написал.

а если мьютексов 10?
PM   Вверх
volatile
Дата 20.2.2011, 16:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(azesmcar @  20.2.2011,  16:07 Найти цитируемый пост)
а если мьютексов 10? 

ну в примере 5 было. В любом случае с десятью goto тоже не шоколадно.
Если десять, двадцать и более, вероятно сделала бы что-то типа небольшого класса, включающего указатель на мьютекс.
в конструкторе try_lock(), в деструкторе, еслио золочен unlock();


Это сообщение отредактировал(а) volatile - 20.2.2011, 16:27
PM MAIL   Вверх
mes
Дата 20.2.2011, 16:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Alexeis @  20.2.2011,  15:04 Найти цитируемый пост)
Исключение это не обязательно крах. Это вполне может быть отрицательный результат проверки

да это не крах.. исключение это не отрицательный, а непредвиденный случай проверки  smile

Добавлено через 3 минуты и 29 секунд
Цитата(Alexeis @  20.2.2011,  15:04 Найти цитируемый пост)
Иногда удобно положительный результат выводить как исключение.  

 smile 



--------------------
PM MAIL WWW   Вверх
Abyx
Дата 20.2.2011, 22:23 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 601
Регистрация: 3.11.2009

Репутация: 1
Всего: 10



исключения С++ слишком медленные, чтобы использовать их иначе кроме как в исключительных ситуациях.
PM MAIL   Вверх
Alexeis
Дата 20.2.2011, 23:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



mes, ну как раз как ты писал. Нашел нужный элемент или проверил, сгенерил исключение и вышел наружу с результатом. Результат можно передать в исключение. Ниже обработки исключения гарантировано освободил все ресурсы. Код получается компактным и прозрачным. 
  А на счет скорости, так это особенности реализации. Кто как реализует у того так и работает.
  


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
mes
Дата 21.2.2011, 00:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Alexeis @  20.2.2011,  22:35 Найти цитируемый пост)
Нашел нужный элемент или проверил, сгенерил исключение и вышел наружу с результатом

но чем return не угодил ?!

и все таки хотелось бы пример реального кода, в котором применение исключения для вышеуказанных целей действительно имеет больше плюсов, чем минусов..

Добавлено через 14 минут и 19 секунд
Цитата(volatile @  20.2.2011,  15:02 Найти цитируемый пост)
Я бы это вообще вот так написал.

ну приз заслужили,  вполне конкурентноспособный вариант.. 
smile


--------------------
PM MAIL WWW   Вверх
Alexeis
Дата 21.2.2011, 00:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Цитата(mes @  21.2.2011,  01:16 Найти цитируемый пост)
но чем return не угодил ?!

  читай ниже. Есть работа которую нужно выполнить перед выходом. А так всего одна точка для выхода где все делается правильно, иначе пришлось бы писать дублирующий код в нескольких местах, что ненадежно и потенциально опасно возможными ошибками.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
mes
Дата 21.2.2011, 00:57 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Alexeis @  20.2.2011,  23:48 Найти цитируемый пост)
Есть работа которую нужно выполнить перед выходом. 

чем RAII не угодил ?


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 21.2.2011, 08:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



volatile

Ну как раз вот этой "елочки" я и пытался избежать smile

Добавлено через 1 минуту и 24 секунды
Цитата(mes @  21.2.2011,  00:57 Найти цитируемый пост)
чем RAII не угодил ? 

присойденяюсь к вопросу.
PM   Вверх
Alexeis
Дата 21.2.2011, 10:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



  Так речь не только о освобождении ресурсов, возможно требуется изменить состояние нескольких объектов. Это может быть объект ядра системы.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
azesmcar
Дата 21.2.2011, 10:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Alexeis

Мне все равно непонятно. Хотелось бы посмотреть на пример, где по твоему кидать исключение вместо return является хорошим решением.
PM   Вверх
Alexeis
Дата 21.2.2011, 10:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Код

LPCTSTR  CCommandParser::DoCommand(LPCTSTR acmd, OUT HANDLE &CmdDone, OUT cmd_status* &Status)
{
    CmdDone = ErrExecDone;

    try
    {
        if (FBusy) throw GetErrorString(err_unit_busy);

        const tstring prefix(VT_DEVICE_NAME_PREF TEXT("."));

        static CmdExecData CED;
        CED.CmdParams.clear();
        if (parse_cmd(acmd, prefix, CED.CmdName, CED.CmdParams))
        {
            CmdMap_class::iterator CmdIt = CmdMap.find(CED.CmdName);

            if (CmdIt != CmdMap.end())
            {
                ResetEvent(CED.CmdExecDone);
                CmdDone           = CED.CmdExecDone;
                CED.ExecFunct     = CmdIt->second;
                CED.CmdExecStatus = &Status;
                TM2->AddAsyncCall(DoAsyncExecCall, &CED);
            }
            else
                throw GetErrorString(err_unknown_command);
        }
        else
            throw GetErrorString(err_unknown_command);

        return TEXT("");
    }
    catch(LPCTSTR reason)
    {
        static cmd_status st = st_error;
        Status = &st;
        SetEvent(ErrExecDone);
        return reason;
    }
}



--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Abyx
Дата 21.2.2011, 11:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 601
Регистрация: 3.11.2009

Репутация: 1
Всего: 10



Код

LPCTSTR DoCommand_impl(LPCTSTR acmd, OUT HANDLE &CmdDone, OUT cmd_status* &Status)
{
     CmdDone = ErrExecDone;

     if(FBusy)
         return GetErrorString(err_unit_busy);

     const tstring prefix(VT_DEVICE_NAME_PREF TEXT("."));
     static CmdExecData CED;
     CED.CmdParams.clear();
     if(!parse_cmd(acmd, prefix, CED.CmdName, CED.CmdParams))
          return GetErrorString(err_unknown_command);

     CmdMap_class::iterator CmdIt = CmdMap.find(CED.CmdName);
     if (CmdIt == CmdMap.end())
         return GetErrorString(err_unknown_command);

     ResetEvent(CED.CmdExecDone);
     CmdDone           = CED.CmdExecDone;
     CED.ExecFunct     = CmdIt->second;
     CED.CmdExecStatus = &Status;
     TM2->AddAsyncCall(DoAsyncExecCall, &CED);

     return TEXT(""); // return NULL ?
}

LPCTSTR  CCommandParser::DoCommand(LPCTSTR acmd, OUT HANDLE &CmdDone, OUT cmd_status* &Status)
{
    LPCTSTR error = DoCommand_impl(acmd, CmdDone, Status);
    if(error && *error) // error == NULL on "no error" ?
    {
        static cmd_status st = st_error;
        Status = &st;
        SetEvent(ErrExecDone);
    }
    return error;
}


Это сообщение отредактировал(а) Abyx - 21.2.2011, 11:19
PM MAIL   Вверх
baldina
Дата 21.2.2011, 11:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(Abyx @  20.2.2011,  22:23 Найти цитируемый пост)
исключения С++ слишком медленные, чтобы использовать их иначе кроме как в исключительных ситуациях. 

за исключением ситуаций, где сама ситуация медленная  smile 
например интерфейс пользователя
PM MAIL   Вверх
Alexeis
Дата 21.2.2011, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Abyx, вот и появилась лишняя сущность на ровном месте smile , а также вызов функции с передачей кучи параметров, а потом еще проверка результата чтобы потом выдать свой результат. Верх читабельности.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Abyx
Дата 21.2.2011, 12:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 601
Регистрация: 3.11.2009

Репутация: 1
Всего: 10



Alexeis, там надо еще больше сущностей. Твоя функция слишком много знает и умеет.
PM MAIL   Вверх
mes
Дата 21.2.2011, 15:42 (ссылка) |   (голосов:4) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Alexeis, спасибо за код.. все стало ясно..  smile
согласен, если писать на С++ не С++-код, то и исключения пригождаются...
smile 

Это сообщение отредактировал(а) mes - 21.2.2011, 15:42


--------------------
PM MAIL WWW   Вверх
volatile
Дата 22.2.2011, 00:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Исключения практически незаменимы при выходе из глубокой рекурсии.
Правда насчет скорости не обращал внимания, надо будет как нибудь замерить, насколько сильно тормозит по сравнению с ретурном.

Добавлено через 2 минуты и 20 секунд
Цитата(mes @  21.2.2011,  00:16 Найти цитируемый пост)
ну приз заслужили, 

mes, thx smile 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.2121 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.