Здравствуйте, Tom, Вы писали:
E>>Может быть и здесь "попадания в молоко" по алгоритму вполне допустимы? Tom>Автор кода сказал, что это только для защиты сделано
Тогда можно у него поинтересоваться, как он гарантирует корректность приложения во для этого оператора:
Здравствуйте, igna, Вы писали:
I>Здравствуйте, Нахлобуч, Вы писали:
Н>>А с каких пор разрешено наследоваться от std::vector?
I>Если в наследующем классе не определять нестатических переменных и виртуальных функций, какие проблемы могут возникнуть?
Да так, мелочи всякие...
5.3.5/3
In the first alternative (delete object), if the static type of the operand is
different from its dynamic type, the static type shall be a base class of the
operand’s dynamic type and the static type shall have a virtual destructor or
the behavior is undefined.
B>5.3.5/3
B>In the first alternative (delete object), if the static type of the operand is
B>different from its dynamic type, the static type shall be a base class of the
B>operand’s dynamic type and the static type shall have a virtual destructor or
B>the behavior is undefined.
B>
Действительно так написано.
И все же, если наследующий класс не добавляет нестатических переменных, а также не определяет виртуальных функций и деструктора, есть реальные причины не требовать определенного поведения? Может быть стандарт подправить, а компиляторы даже переделывать не придется?
Здравствуйте, igna, Вы писали:
I>Здравствуйте, Bell, Вы писали:
B>>
B>>5.3.5/3
B>>In the first alternative (delete object), if the static type of the operand is
B>>different from its dynamic type, the static type shall be a base class of the
B>>operand’s dynamic type and the static type shall have a virtual destructor or
B>>the behavior is undefined.
B>>
I>Действительно так написано.
I>И все же, если наследующий класс не добавляет нестатических переменных, а также не определяет виртуальных функций и деструктора, есть реальные причины не требовать определенного поведения?
К примеру:
#include <iostream>
using namespace std;
struct base
{
//virtual ~base() {}
};
class d : public base
{
public:
static void* operator new(size_t sz);
static void operator delete(void* ptr, size_t sz);
};
void* d::operator new(size_t sz)
{
cout << "d::new" << endl;
//Возможно, своя хитрая реализацияreturn ::operator new(sz);
}
void d::operator delete(void* ptr, size_t sz)
{
cout << "d::delete" << endl;
//Возможно, своя хитрая реализация
::operator delete(ptr);
}
int main ()
{
base* pb = new d();
delete pb;
return 0;
}
Без виртуального деструктора могут получиться весьма занимательные вещи.
Далее идет множественное наследование...
Может быть стандарт подправить, а компиляторы даже переделывать не придется?
Напиши formal proposal
Здравствуйте, Tom, Вы писали:
E>>Фактически же он подсовывает мусор, который затем где-нибудь обязательно даст себя знать. Tom>Ничего он не гарантирует, ди оно и падает
Ну так и скажи: "Господин хороший, ваши гарантии безопасности, как оказалось, ничего не гарантируют. Так позвольте вас спросить -- какого <здесь подставляется любое слово, хорошо отражающее степень твоего недоумения> вся эта ерунда (слово ерунда вполне возможно заменить на соответствующий нецензурный аналог) здесь делает?"
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[10]: вектор и границы
От:
Аноним
Дата:
29.09.05 14:12
Оценка:
Здравствуйте, GregZ, Вы писали:
GZ>Здравствуйте, Анатолий Широков, Вы писали:
GZ>>>Я — скорее всего не буду. GZ>>>Сторонний человек использующий мой контейнер — вполне вероятно. АШ>>Но это не повод отказываться от наследования.
GZ>Интересное мнение. Я конечно не параноик, но предпочитаю перестраховываться. GZ>Может тогда кто объяснит мне почему же нет таки виртуальных деструкторов у стандартных контейнеров?
Насколько я понимаю, это сделано по той же причине, по которой у контейнеров нет общего базового класса. Т.е: иерархии контейнерных классов — зло, программист всегда должен четко понимать с каким контейнером он работатет и тогда он вегда будет знать сколько стоит та или иная операция с ним.
Здравствуйте, Tom, Вы писали:
Tom>Вот сижу делаю ревью чужого кода:
У нас похожее чудо используется
namespace std
{
template <class T, class A>
class OurVector
{
};
}
#define vector OurVector
Сделан был для того, что бы унифицированно использовать старый рукопсиный унаследованный вектор с std::vector, +понаставлены ассерты, +немного оптимизирован под наш менеджер памяти, +переносит объекты по памяти memcpy вместо , new(NewPlace) T(Old), Old->~T(), выкинута вся excepetion safity.
Правильно работающая программа — просто частный случай Undefined Behavior
АШ>Я далек от мысли, что все стандартные контейнеры вы используете по следующей схеме:
Мне намного сложнее читать код, находящийся внутри отнасдедованного от контейнера класса, так как народ у нас
наследуется от контейнера и пишет свои бизнес классы — не контейнеры, правда слава богу такой один (человек), а не все
Здравствуйте, Tom, Вы писали:
Tom>наследуется от контейнера и пишет свои бизнес классы — не контейнеры, правда слава богу такой один (человек), а не все
Здравствуйте, eao197, Вы писали:
E>Ну так и скажи: "Господин хороший, ваши гарантии безопасности, как оказалось, ничего не гарантируют. Так позвольте вас спросить -- какого <здесь подставляется любое слово, хорошо отражающее степень твоего недоумения> вся эта ерунда (слово ерунда вполне возможно заменить на соответствующий нецензурный аналог) здесь делает?"
Я делал примерно такую штуку, когда меня совсем достало. Возвращал объект, который на все вопросы отвечал exception. Логика такого требовала, нужна была только ссылка.
E>Наиболее гуманным кажется предложение альтернативной реализации и демонстрация ее преимуществ. Но не укор.
Ты имеешь ввиду отправить рассматривать std::vector? Или книжку отправить читать?
Tom>Ты имеешь ввиду отправить рассматривать std::vector? Или книжку отправить читать?
Книжки, конечно, нужно отправить читать. Но в книжках не написано, как лучше поступить конкретно в данной ситуцаии — для этого уже нужен опыт. Потому посадить за монитор рядом с собой, и дать этот опыт — показать, как бы реализация данной задачи выглядела лучше. И почему лучше.
Здравствуйте, GlebZ, Вы писали:
GZ>Я делал примерно такую штуку, когда меня совсем достало. Возвращал объект, который на все вопросы отвечал exception. Логика такого требовала, нужна была только ссылка.
А вот это уже pattern Null Object.
Re[2]: вектор и границы
От:
Аноним
Дата:
29.09.05 17:35
Оценка:
Здравствуйте, _Winnie, Вы писали:
_W>Здравствуйте, Tom, Вы писали:
Tom>>Вот сижу делаю ревью чужого кода:
_W>У нас похожее чудо используется
_W>
_W>namespace std
_W>{
_W>template <class T, class A>
_W>class OurVector
_W>{
_W>};
_W>}
_W>#define vector OurVector
_W>
_W>Сделан был для того, что бы унифицированно использовать старый рукопсиный унаследованный вектор с std::vector, +понаставлены ассерты, +немного оптимизирован под наш менеджер памяти, +переносит объекты по памяти memcpy вместо , new(NewPlace) T(Old), Old->~T(), выкинута вся excepetion safity.
блин, это же труба. у нас тоже свой вектор, т.к. проект начинался в 93ем, но до такого слава Богу не доходит.
я описывал задачку по решению СЛАУ большой размерности. Так для ее решения я как раз использовал подобный фокус. И он был оправдан тем, что в определенные ячейки матрицы всегда помещались нули. Эти нули получались в результате каких-то хитрых расчетов и никогда затем не использовались. В таких условиях проще было позволить писать в "молоко", чем преобразовывать сложный алгоритм первоначального заполнения матрицы.
E>Может быть и здесь "попадания в молоко" по алгоритму вполне допустимы?
Судя по названию класса SafeVector это не тот случай :)
You will always get what you always got
If you always do what you always did
Re[6]: вектор и границы
От:
Аноним
Дата:
29.09.05 19:19
Оценка:
Сдаюсь.
Проблема следующая:
Две специализации basic_string отличающиеся только типом аллокатора, то есть basic_string<Ch, Tr, A1> и basic_string<Ch, Tr, A2> нельзя присваивать друг другу, конструировать друг из друга и так далее. Определил свой производный от basic_string шаблон класса (назовем его к примеру my_basic_string), который можно использовать везде, где можно использовать basic_string, и который к тому же разрешает присваивание my_basic_string<Ch, Tr, A1> и my_basic_string<Ch, Tr, A2> друг другу и прочее. Но у basic_string деструктор невиртуален ...
В my_basic_string переопределены все конструкторы basic_string и (невиртуальные) функции basic_string принимающие аргумент типа basic_string, больше там нет ничего.