Здравствуйте, Bell, Вы писали:
B>В данном да. Но ИМХО всегда следует придеживаться определенных правил. При программировании на С++ самодисциплина играет далеко не самую последнюю роль.
Правило "Не делать наследования от классов без виртуального деструктора" является одним из тех ложных правил, которые были популярны среди С++ программистов среднего примерно пару лет назад. Это правило успешно умерло, как и другие ложные правила типа "Каждая функция должна иметь только одну точку выхода" и т.п. Точнее, это правило не сколько умерло, сколько наконец отодвинулось на свое правильное место — в узкую область классического ООП программирования на С++ с применением динамического полиморфизма.
По моему мнению, причина ошибочной популярности этого правила, как глобального С++ правила, заключалась в том, что не очень хорошо подготовленным читателям стало доступно большое количество книг по классическому ООП на С++ (хороших книг, надо сказать), которые они тем не менее ошибочно принимали за универсальные книги по С++.
Мне странно видеть, что это ложное правило еще живет в этой конференции. Наследовать от стандартных контейнеров можно и нужно, в тех ситуациях, когда это оправданно. Наличие или отсутсвие виртуального деструтора при этом никакой роли не играет. Виртуальный деструктор — атрибут полиморфного класса. Здесь же никто не пытается создать полиморфный класс.
ЗХ>>фраза "Контейнеры STL не предназначены для наследования" означает. что у них нет виртуальных методов, которые можно было бы переопределить в наследнике. B>В том числе у них нет виртуального деструктора.
Это соврешнно не важно. Это означает, только то, что такие объекты не являются полиморфно-удаляемыми и не более. Тем не менее это не повод отказываться от наследования, если это действительно необходимо. В generic programming наследование применяется для достижения подобных целей повсеместно. Задаваться при этом вопросом о каком-то виртуальном деструкторе, мягко говоря, неуместно.
ЗХ>>...а для расширения функциональности паблик-наследование самое оно. B>Спорное утверждение, ну да ладно...
Это утверждение перестало быть спорным довольно давно. Строго говоря, такое применение публичного наследования упоминает еще Страуструп в D&E. Александреску в "Modern C++ Design" использует публичное наследование для подобных целей приктически повсеместно.
ЗХ>>...либо делать обертки ко всем его операциям. B>Да, интерфейс придется повторить. Это так ужасно?
Это соврешенно неприемлемо. Да и зачем, если есть публичное наследование?
Здравствуйте, Зверёк Харьковский, Вы писали:
B>>Контейнеры STL не предназначены для наследования. Лучше используй включение.
ЗХ>ну, это, ИМХО, для данного случая по-барабану
В данном да. Но ИМХО всегда следует придеживаться определенных правил. При программировании на С++ самодисциплина играет далеко не самую последнюю роль.
ЗХ>фраза "Контейнеры STL не предназначены для наследования" означает. что у них нет виртуальных методов, которые можно было бы переопределить в наследнике.
В том числе у них нет виртуального деструктора.
ЗХ>...а для расширения функциональности паблик-наследование самое оно.
Спорное утверждение, ну да ладно...
ЗХ>...а при включении пришлось бы либо делать включенный контейнер паблик-членом. что не есть гут,
А это еще зачем?!
ЗХ>...либо делать обертки ко всем его операциям.
Да, интерфейс придется повторить. Это так ужасно?
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, Tan4ik, Вы писали:
B>Контейнеры STL не предназначены для наследования. Лучше используй включение.
ну, это, ИМХО, для данного случая по-барабану
фраза "Контейнеры STL не предназначены для наследования" означает. что у них нет виртуальных методов, которые можно было бы переопределить в наследнике. а для расширения функциональности паблик-наследование самое оно. а при включении пришлось бы либо делать включенный контейнер паблик-членом. что не есть гут, либо делать обертки ко всем его операциям.
Здравствуйте, Андрей, Вы писали:
ЗХ>>> фраза "Контейнеры STL не предназначены для наследования" означает. что у них нет ЗХ>>> виртуальных методов, которые можно было бы переопределить в наследнике.
B>> В том числе у них нет виртуального деструктора.
AT> соврешнно не важно. Это означает, только то, что такие объекты не являются AT> полиморфно-удаляемыми и не более.
Невиртуальность членов std::vector, помимо того, что, в частности, объекты унаследованного
класса (VectorEx) не являются полиморфно-удаляемыми, в общем, приводит еще и к тому, что
инварианты VectorEx могут нарушаться, если где-нибудь есть модификация объектов VectorEx
через ссылки/указатели на std::vector.
B>> Да, интерфейс придется повторить. Это так ужасно?
АТ> Это соврешенно неприемлемо. Да и зачем, если есть публичное наследование?
Еще лучшим вариантом, вероятно, было бы наличие какого-нибудь встроенного механизма,
позволяющего получить в VectorEx тот же интерфейс, что и в std::vector, но не позволять,
по крайней мере, неявное приведение VectorEx* -> std::vector*.
P.S. естественно, если инварианты VectorEx тождественны инвариантам std::vector,
упомянутых проблемы не имеют никакого значения.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Tan4ik, Вы писали:
T>int main() T>{ T> mytype a = 2; T> assert(a.size() == 1); T> assert(a[0] == 2); T> return 0; T>} T>[/ccode]
T>Код конечно не компилируется.
Вдобавок ко всем прозвучавшим пинкам добавлю свои 5 копеек:
в инструкции
T> mytype a = 2;
происходит не вызова operator=, а вызов конструктора.
Если хочешь, чтобы вызывался operator=, пиши так
mytype a;
a = 2;
А вообще, если тебе нужна подобная функциональность, то используй не std::vector, а std::valarray (мне показалось, что он больше подойдет к твоим неозвученным нуждам)
J>Вдобавок ко всем прозвучавшим пинкам добавлю свои 5 копеек:
J>в инструкции J>
T>> mytype a = 2;
J>
J>происходит не вызова operator=, а вызов конструктора.
Я об этом говорил
J>А вообще, если тебе нужна подобная функциональность, то используй не std::vector, а std::valarray (мне показалось, что он больше подойдет к твоим неозвученным нуждам)
Да, наверное.
Любите книгу — источник знаний (с) М.Горький
Re[3]: vector<int> = int
От:
Аноним
Дата:
24.10.03 08:51
Оценка:
Здравствуйте, sercher, Вы писали:
ЗХ>>угу. operator= обязан быть мембером
S> Или friend-ом.
J>А вообще, если тебе нужна подобная функциональность, то используй не std::vector, а std::valarray (мне показалось, что он больше подойдет к твоим неозвученным нуждам)
valarray<T>& operator=(const T& x);
member operator replaces each element of the controlled sequence with a copy of x
resize(1) ему бы сделать предварительно...
Просто фунционатьность vector меня бы вполне устроила. Сейчас написал вот так:
class myclass : public vector<int>
{
public:
myclass& operator=(int a)
{
(*this).assign(1,a);
return *this;
}
};
Контейнеры STL не предназначены для наследования. Лучше используй включение.
Любите книгу — источник знаний (с) М.Горький
Re[5]: vector<int> = int
От:
Аноним
Дата:
24.10.03 10:09
Оценка:
Здравствуйте, Зверёк Харьковский, Вы писали:
B>>Контейнеры STL не предназначены для наследования. Лучше используй включение.
ЗХ>ну, это, ИМХО, для данного случая по-барабану
ЗХ>фраза "Контейнеры STL не предназначены для наследования" означает. что у них нет виртуальных методов,
На практике она означает, что Вы получили еще одну возможность достичь неопределенного поведения без диагностики со стороны компилятора.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Зверёк Харьковский, Вы писали:
B>>>Контейнеры STL не предназначены для наследования. Лучше используй включение.
ЗХ>>ну, это, ИМХО, для данного случая по-барабану
ЗХ>>фраза "Контейнеры STL не предназначены для наследования" означает. что у них нет виртуальных методов,
А>На практике она означает, что Вы получили еще одну возможность достичь неопределенного поведения без диагностики со стороны компилятора.
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, Зверёк Харьковский, Вы писали:
B>>>Контейнеры STL не предназначены для наследования. Лучше используй включение.
ЗХ>>ну, это, ИМХО, для данного случая по-барабану B>В данном да. Но ИМХО всегда следует придеживаться определенных правил. При программировании на С++ самодисциплина играет далеко не самую последнюю роль.
правила — правилами. но для соответствующих задач нужно использовать соответствующие решения.
ЗХ>>фраза "Контейнеры STL не предназначены для наследования" означает. что у них нет виртуальных методов, которые можно было бы переопределить в наследнике. B>В том числе у них нет виртуального деструктора.
ой. это да. тут ничего не попишешь. тормозю...
ЗХ>>...а для расширения функциональности паблик-наследование самое оно. B>Спорное утверждение, ну да ладно...
спорное — давай спорить
ЗХ>>...а при включении пришлось бы либо делать включенный контейнер паблик-членом. что не есть гут, B>А это еще зачем?!
а чтоб обертки не делать
ЗХ>>...либо делать обертки ко всем его операциям. B>Да, интерфейс придется повторить. Это так ужасно?
когда нужно добавить всего 1 операцию, и ту для прикола, а больше ничего менять не надо, это — не лучшее решение. просто противно, в конце концов. сложность решения должна быть пропорциональна сложности задачи. хотя бы иногда.
FAQ — це мiй ай-кью!
Re[7]: vector<int> = int
От:
Аноним
Дата:
24.10.03 10:37
Оценка:
Здравствуйте, Зверёк Харьковский, Вы писали:
А>>На практике она означает, что Вы получили еще одну возможность достичь неопределенного поведения без диагностики со стороны компилятора.
ЗХ>это почему же?
Потому, что при открытом наследовании Вы получаете возможность удалять производный объект через указатель на базовый.
ЗХ>>>фраза "Контейнеры STL не предназначены для наследования" означает. что у них нет виртуальных методов, которые можно было бы переопределить в наследнике. B>>В том числе у них нет виртуального деструктора. ЗХ>ой. это да. тут ничего не попишешь. тормозю...
И чем это грозит?
Извините за глупые вопросы, я на cpp недавно.
---
С уважением,
Лазарев Андрей
Re[8]: vector<int> = int
От:
Аноним
Дата:
24.10.03 10:41
Оценка:
Здравствуйте, Tan4ik, Вы писали:
B>>>В том числе у них нет виртуального деструктора. ЗХ>>ой. это да. тут ничего не попишешь. тормозю...
T>И чем это грозит?
Неопределенным поведением при удалении через указатель на базовый класс.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Зверёк Харьковский, Вы писали:
А>>>На практике она означает, что Вы получили еще одну возможность достичь неопределенного поведения без диагностики со стороны компилятора.
ЗХ>>это почему же?
А>Потому, что при открытом наследовании Вы получаете возможность удалять производный объект через указатель на базовый.
А>>>На практике она означает, что Вы получили еще одну возможность достичь неопределенного поведения без диагностики со стороны компилятора.
ЗХ>>это почему же?
А>Потому, что при открытом наследовании Вы получаете возможность удалять производный объект через указатель на базовый.
А если я так удалять не буду? И запомню, что делаю нехорошо.
Все работать будет?
А если буду, но производный класс не содержит дополнительных переменных?
T>>И чем это грозит?
А>Неопределенным поведением при удалении через указатель на базовый класс.
А в остальном все будет работать корректно?
---
С уважением,
Лазарев Андрей
Re[9]: vector<int> = int
От:
Аноним
Дата:
24.10.03 10:49
Оценка:
Здравствуйте, Зверёк Харьковский, Вы писали:
А>>>>На практике она означает, что Вы получили еще одну возможность достичь неопределенного поведения без диагностики со стороны компилятора.
ЗХ>>>это почему же?
А>>Потому, что при открытом наследовании Вы получаете возможность удалять производный объект через указатель на базовый.
ЗХ>ну и что?
Неопределенное поведение, как и было сказано.
Re[10]: vector<int> = int
От:
Аноним
Дата:
24.10.03 10:50
Оценка:
Здравствуйте, Tan4ik, Вы писали:
T>>>И чем это грозит?
А>>Неопределенным поведением при удалении через указатель на базовый класс.
T>А в остальном все будет работать корректно?
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Зверёк Харьковский, Вы писали:
А>>>>>На практике она означает, что Вы получили еще одну возможность достичь неопределенного поведения без диагностики со стороны компилятора.
ЗХ>>>>это почему же?
А>>>Потому, что при открытом наследовании Вы получаете возможность удалять производный объект через указатель на базовый.
ЗХ>>ну и что?
А>Неопределенное поведение, как и было сказано.
( шизофрения, как и было сказано (c) Булгаков? )
ну при отсутствии виртуального деструктора — таки да. но с эти я уже согласился.
Здравствуйте, Tan4ik, Вы писали:
А>>>>На практике она означает, что Вы получили еще одну возможность достичь неопределенного поведения без диагностики со стороны компилятора.
ЗХ>>>это почему же?
А>>Потому, что при открытом наследовании Вы получаете возможность удалять производный объект через указатель на базовый.
T>А если я так удалять не буду? И запомню, что делаю нехорошо.
запомню — это не есть хорошо...
потом придет кто-нибудь твою прогу поддерживать — и гаплык.
насчет запомню — это целая философия.
понимаешь, многие вещи вместо того чтобы вставлять ограничения в код. можно написать в доках — не делайте того, не делайте этого.
но спасибо тебе никто не скажет
такие, блин, пирожки с котятами — их ешь, а они мяукают.
T>А если буду, но производный класс не содержит дополнительных переменных?
хрен его знает
T>P.S. Это уже чисто познавательный интерес.
FAQ — це мiй ай-кью!
Re[11]: vector<int> = int
От:
Аноним
Дата:
24.10.03 12:06
Оценка:
Здравствуйте, Зверёк Харьковский, Вы писали:
А>>>>Потому, что при открытом наследовании Вы получаете возможность удалять производный объект через указатель на базовый.
ЗХ>>>ну и что?
А>>Неопределенное поведение, как и было сказано.
ЗХ>( шизофрения, как и было сказано (c) Булгаков? )
ЗХ>ну при отсутствии виртуального деструктора — таки да.
И мне жаль! (c)
Re[10]: vector<int> = int
От:
Аноним
Дата:
24.10.03 12:08
Оценка:
Здравствуйте, Зверёк Харьковский, Вы писали:
T>>А если буду, но производный класс не содержит дополнительных переменных?
ЗХ>хрен его знает
Независимо. Стандарту здесь важно только несовпадение динамического и статического типов при отсутствии виртуального деструктора.
Здравствуйте, Аноним, Вы писали:
А>>>На практике она означает, что Вы получили еще одну возможность достичь неопределенного поведения без диагностики со стороны компилятора.
ЗХ>>это почему же?
А>Потому, что при открытом наследовании Вы получаете возможность удалять производный объект через указатель на базовый.
Используемая Вами логика примерно аналогична совету избегать использования в С++ коде операции деления, т.к. она может привести к делению на нуль.
Это не повод избегать наследования в данном конкретном случае. Это повод не удалять производный объект через указатель на базовый, но не более.
Best regards,
Андрей Тарасевич
Re[9]: vector<int> = int
От:
Аноним
Дата:
25.10.03 08:33
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:
А>>>>На практике она означает, что Вы получили еще одну возможность достичь неопределенного поведения без диагностики со стороны компилятора.
АТ>Используемая Вами логика примерно аналогична совету избегать использования в С++ коде операции деления, т.к. она может привести к делению на нуль.
Вы напрасно усмотрели в моем утверждении какую-то оценочность. Ее там нет.
Я советую лишь, используя операцию деления, знать, что деление на ноль приведет к неопределенному поведению.