Re[6]: вектор и границы
От: jazzer Россия Skype: enerjazzer
Дата: 29.09.05 19:20
Оценка: 1 (1) +2 :)
Здравствуйте, GregZ, Вы писали:

GZ>Здравствуйте, Анатолий Широков, Вы писали:


GZ>>>Т.е. для вас вполне приемлемо создать собственный контейнер, открыто наследуясь от какого-либо стандартного контейнера?


АШ>>Простите, а кто Вам внушил обратное — то есть, что это делать нельзя?


GZ>По-моему отсутствие виртуального деструктора у стандартных контейнеров говорит об этом достаточно красноречиво.


Значит, говоришь, если у класса нет виртуального деструктора, от него нельзя наследоваться?
Сейчас я тебя напугаю.
Лучше сразу сядь, прежде чем читать то, что я сейчас напишу.

Если ты внимательно посмотришь в Стандарт в части STL — ты увидишь множество случаев наследования БЕЗ виртуального деструктора в базовом классе.

Например, классы std::unary_function и std::binary_function не содержат виртуальных деструкторов.
Тем не менее, всякие std::plus, std::equal_to и прочие функторы, биндеры и адаптеры от них успешно наследуются публичным образом.

Та же ситуация с тегами итераторов (24.3.3/1).
namespace std {
     struct input_iterator_tag {};
     struct output_iterator_tag {};
     struct forward_iterator_tag: public input_iterator_tag {};
     struct bidirectional_iterator_tag: public forward_iterator_tag {};
     struct random_access_iterator_tag: public bidirectional_iterator_tag {};
}


Более того, все то же самое происходит и с самими итераторами (24.4.1.1) и инсертерами (24.4.2.1):
class reverse_iterator : public iterator


Хуже того, они сами и рекомендуют наседоваться от этого ужасного класса без виртуального деструктора:
24.3.3/4 [Example: If a C++ program wants to define a bidirectional iterator for some data structure containing
double and such that it works on a large memory model of the implementation, it can do so with:

class MyIterator :
   public iterator<bidirectional_iterator_tag, double, long, T*, T&> {
                                // code implementing ++, etc.
};
Then there is no need to specialize the iterator_traits template. —end example]


Так что опасность открытого наследования без виртуального деструктора очень сильно преувеличена :)
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[7]: вектор и границы
От: igna Россия  
Дата: 29.09.05 19:23
Оценка:
Это был я, igna.
Re[7]: вектор и границы
От: GregZ СССР  
Дата: 30.09.05 05:34
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Если ты внимательно посмотришь в Стандарт в части STL — ты увидишь множество случаев наследования БЕЗ виртуального деструктора в базовом классе.

...<выцарапано>...
J>Так что опасность открытого наследования без виртуального деструктора очень сильно преувеличена

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

Обобщу: (если что понял неправильно, поправьте)
Отсутствие виртуального деструктора в стандартных контейнерах говорит о том, что их классы не предполагается использовать как полиморфные, но при этом не запрещается открыто от них наследоваться (с учетом того, что и дальше будет использоваться эта парадигма). Одним из плюсов является отсутствие таблицы vptr, за которую не приходится переплачивать дополнительно расходуемой памятью. При этом предполагается что пользователь производного контейнера знает об этой специфике.
Re[8]: вектор и границы
От: leper Россия  
Дата: 30.09.05 06:38
Оценка: +1
GregZ wrote:

> Обобщу: *(если что понял неправильно, поправьте)*

> Отсутствие виртуального деструктора в стандартных контейнерах говорит о
> том, что их классы *не* предполагается использовать как полиморфные

Точнее, не предполагается *полиморфное удаление* данных классов.
Posted via RSDN NNTP Server 2.0 beta
Think for yourself. Question authory.
Re[10]: вектор и границы
От: srggal Украина  
Дата: 30.09.05 07:16
Оценка:
Здравствуйте, Centaur, Вы писали:

C>Здравствуйте, GlebZ, Вы писали:


GZ>>Я делал примерно такую штуку, когда меня совсем достало. Возвращал объект, который на все вопросы отвечал exception. Логика такого требовала, нужна была только ссылка.


C>А вот это уже pattern Null Object.


ИМХО: знание паттернов, не освобождает от ответственности за их применение, какой-бы это ни был паттерн

pattern Null Object


или pattern Moc-reference (название собственное, шутливое, искаьт доку по этому паттерну не стоит )
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[9]: вектор и границы
От: srggal Украина  
Дата: 30.09.05 07:42
Оценка:
Здравствуйте, leper, Вы писали:

L>GregZ wrote:


L>Точнее, не предполагается *полиморфное удаление* данных классов.


А если уточнить, под термином

*полиморфное удаление*


Понимается

    int    *pFoo    = new int(0);
        ...
    delete pFoo;


что зачастую означает то, что потомки таких классов — не должны производить каких-либо динамических распределений памяти, освобождение которой потребуется в деструкторе; либо, в свою очередь, сами потомки никогда не создаются динамически (поэтому и не требуется их "полиморфное удаление".

тема избитая, пример:

#include "stdafx.h"

struct foo
{
    foo()
    {
        std::cout << __FUNCTION__ << std::endl;
    }

    ~foo()
    {
        std::cout << __FUNCTION__ << std::endl;
    }
};

struct bar
    :    public    foo
{
    bar()
    {
        std::cout << __FUNCTION__ << std::endl;
    }

    virtual ~bar()
    {
        std::cout << __FUNCTION__ << std::endl;
    }
};

struct poly_foo
{
    poly_foo()
    {
        std::cout << __FUNCTION__ << std::endl;
    }

    virtual ~poly_foo()
    {
        std::cout << __FUNCTION__ << std::endl;
    }
};

struct poly_bar
    :    public    poly_foo
{
    poly_bar()
    {
        std::cout << __FUNCTION__ << std::endl;
    }

    virtual ~poly_bar()
    {
        std::cout << __FUNCTION__ << std::endl;
    }
};


int _tmain(int argc, _TCHAR* argv[])
{
    {
        std::cout << " ------- Test bar ------- " << std::endl;
        foo    *pFoo_ = new bar;
        delete pFoo_;
    }

    {
        std::cout << " ------- Test poy_bar  ------- " << std::endl;

        poly_foo    *pFoo_ = new poly_bar;
        delete pFoo_;
    }

    return 0;
}


ИМХО: необдуманное следование догмам — есть фанатизм, который зло, по своей сути, и этого следует избегать, путем обдумывания догм, и принития оных через осмысление.

ЗЫ: Во я загнул
... << RSDN@Home 1.1.4 stable rev. 510>>
Re: вектор и границы
От: Serpent_T.B.  
Дата: 30.09.05 12:24
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>Вот сижу делаю ревью чужого кода:

...

Tom>Как вам такое? Я вот думаю как бы помягче обьяснить человеку, что он не прав.



Такой контейнер, конечно, неплохо использовать с целью скорее не для проверки диапазона, а для экономии ресурсов — в случае, если выполняется много обращений на чтение елементов
const_reference []()
за пределами массива. ssm и eao197 об этом уже сказали, но есть один ньюанс (чуть ниже). И опять же — тогда не "SafeVector". Иначе — действительно at().


IMHO, если чтобы не обидеть, нужно ему обьяснить, что надо переписать реализацию НЕконстантного оператора [] (Пока в m_FakeItem ничего не пишем — конечно, всё и так работает неплохо )

Т.е., сделать что-то вроде copy-on-write — при вызове НЕконстантного оператора [] расширять и заполнять вектор до указанного индекса m_FakeItem'ами.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.