Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Использование собственного инициализатора


Автор: Kuvaldis 16.10.2007, 01:53
Наткнулся на такую задачку у Страуструпа:
Найдите пример, когда имеет смысл воспользоваться именем в его собственном инициализаторе.
Как я понимаю, должно быть что-то вроде такого:
Код

int x = x;

Но моя башка отказывается производить какие-либо здравые идеи.
Что имел в виду Страуструп?

Автор: Daevaorn 16.10.2007, 08:28
Код

struct Foo
{
    int bar;
    Foo(int bar):bar(bar){}
};

?

Автор: archimed7592 16.10.2007, 09:03
Daevaorn, ну это же имена разных сущностей smile.

Автор: Daevaorn 16.10.2007, 09:08
Цитата(archimed7592 @  16.10.2007,  10:03 Найти цитируемый пост)
, ну это же имена разных сущностей 

но одинаковые же имена;)

Автор: akizelokro 16.10.2007, 09:43
"Найдите пример, когда имеет смысл воспользоваться именем в его собственном инициализаторе."

Раз ни у кого нет здравых замечаний, тогда уже пропишусь я. Подобный пример приведен у Стэнли Б.Липпмана. Daeavaorn прописал только окончание примера. Пример используется для обучения новичков (используется в образовательных целях), чтобы рассмотреть область видимости класса.

Код

int _height;

class Screen {
public:
   Screen( int _height ) {
      _height = 0;   // к чему относится _height? К параметру
      this->_height = 0;   // относится к Screen::_height
      // тоже правильно:
      // Screen::_height = 0;
   }
private:
   short _height;
};


Ну, здесь я прикопался к словам автора темы. Специально для экспертов поясню, что это шутка.

Автор: Kuvaldis 16.10.2007, 10:07
Daevaorn, akizelokro, правы, черт возьми. А я тупанул :(
Вопрос закрыт.

Автор: akizelokro 16.10.2007, 10:18
Теперь без шуточек. У Страуструпа написано, что иногда важен порядок инициализации. Возможно ли это объяснение?
Еще я вчера ковырялся над примером, как обойти обязательную инициализацию const члена класса. Пробовал это сделать через union, но посчитал, что анонимное объединение накладывает слишком много дополнительных требований, поэтому попытался выкинуть фортель вида

Код

class M1
{
  const struct Mqqq...{....};
  ...
};

class M2
{
  struct Mqqq...{....};
  ...
};

M1* m1 = new M1;
// присвоения значений
M2 * m2 = new (m1) M2;


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

Автор: archimed7592 16.10.2007, 10:27
Цитата(akizelokro @  16.10.2007,  10:18 Найти цитируемый пост)
Теперь без шуточек. У Страуструпа написано, что иногда важен порядок инициализации. Возможно ли это объяснение?

Не совсем понимаю фразу "возможно ли это объяснение?", но, осмелюсь предположить, что ты просишь объяснить что это значит... Объясняю:
Код

class A
{
    double r;
    double x;
    double y;
public:
    A(double x_, double y_)
        : x(x_), y(y_), r(x * x + y * y)
    { }
    // в реальности порядок будет следующий:
    // r, x, y - мусор
    // r = x * x + y * y = мусор в квадрате + мусор в квадрате = мусор
    // x = x_
    // y = y_
}



Цитата(akizelokro @  16.10.2007,  10:18 Найти цитируемый пост)
поэтому попытался выкинуть фортель вида

Я считаю, что чем "выкидывать фортеля" лучше подумать как перепроектировать эту сущность так, чтобы фортеля не понадобились.

Автор: akizelokro 16.10.2007, 11:14
Нет, с этим примером то как раз все понятно. Правильно задать вопрос я сейчас просто не могу, так что вам придется подождать.

Код

Я считаю, что чем "выкидывать фортеля" лучше подумать как перепроектировать эту сущность так, чтобы фортеля не понадобились. 


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


Автор: maxim1000 16.10.2007, 13:05
а что, если так:
Код

struct ListItem
{
    int Value;
    ListItem *Next;
    ListItem(int value,ListItem *next):Value(value),Next(next) {}
};

ListItem loop(1,&loop);

?

Автор: archimed7592 16.10.2007, 13:55
Гхм... Вродь как имя инжектиться в scope только после declaration-statement... Почему тогда это компилируется? 0_о

Добавлено через 18 секунд
(mingw-g++-3.4.2)

Автор: maxim1000 16.10.2007, 14:30
smile
вообще-то я не пробовал скомпилить, просто пытался придумать ситуацию, когда это теоретически может пригодиться, не обязательно корректную...

Автор: archimed7592 16.10.2007, 14:39
И тем не менее, вопрос, почему это компилируется остаётся открытым smile.

Автор: UnrealMan 16.10.2007, 18:00
Цитата(maxim1000 @  16.10.2007,  15:30 Найти цитируемый пост)
вообще-то я не пробовал скомпилить, просто пытался придумать ситуацию, когда это теоретически может пригодиться, не обязательно корректную... 

Вполне корректный (с точки зрения компилируемости) код.

Автор: SergeCpp 16.10.2007, 23:26
Относительно заглавного вопроса темы, помнится, http://sergecpp.mylivepage.ru/file/1/701/

Код
void LifeView::DrawFull( BYTE* ArrayScan, long beg_x, long beg_y, UINT cnt_x, UINT cnt_y )
{
    do
    {
        long beg_x( beg_x );
        UINT cnt_x( cnt_x );

        // bulk

        while( cnt_x >= ADJ_ELEMS )
        {
//... файл LifeView.cpp


Автор: UnrealMan 17.10.2007, 10:29
Цитата(SergeCpp @ 17.10.2007,  00:26)
Относительно заглавного вопроса темы, помнится, http://sergecpp.mylivepage.ru/file/1/701/

Код
void LifeView::DrawFull( BYTE* ArrayScan, long beg_x, long beg_y, UINT cnt_x, UINT cnt_y )
{
    do
    {
        long beg_x( beg_x );
        UINT cnt_x( cnt_x );

        // bulk

        while( cnt_x >= ADJ_ELEMS )
        {
//... файл LifeView.cpp

С таким же успехом ты мог использовать

Код
void LifeView::DrawFull( BYTE* ArrayScan, long beg_x, long beg_y, UINT cnt_x, UINT cnt_y )
{
    do
    {
        long beg_x;
        UINT cnt_x;

        // bulk

        while( cnt_x >= ADJ_ELEMS )
        {
//... файл LifeView.cpp


Добавлено через 3 минуты и 42 секунды
Если только ты не на VC++6.0 это писал - он нарушает стандарт и инициализирует локальные переменные значениями одноимённых переменных из внешней области видимости.

Автор: archimed7592 17.10.2007, 10:50
Цитата(UnrealMan @  17.10.2007,  10:29 Найти цитируемый пост)
С таким же успехом ты мог использовать

С какого перепугу? scope разные...
Покажи, где в стандарте сказано, что так нельзя...

Автор: UnrealMan 17.10.2007, 11:15
Цитата(3.3.1 Point of declaration)
The point of declaration for a name is immediately after its complete declarator (clause 8) and before its initializer (if any), except as noted below.

Данный случай не подпадает под исключения.

Цитата
declarator:
    direct-declarator
    ptr-operator declarator

direct-declarator:
    declarator-id
    direct-declarator ( parameter-declaration-clause ) cv-qualifier-seqopt exception-specificationopt
    direct-declarator [ constant-expressionopt ]
    ( declarator )

declarator-id:
    id-expression
    ::opt nested-name-specifieropt type-name

id-expression:
    unqualified-id
    qualified-id

unqualified-id:
    identifier
    operator-function-id
    conversion-function-id
    ˜ class-name
    template-id

Цитата
initializer:
    = initializer-clause
    ( expression-list )


Автор: archimed7592 17.10.2007, 11:21
Ок, спасибо.

Автор: akizelokro 17.10.2007, 13:24
Цитата

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


Все-таки я грешу на порядок инициализации. Если, конечно, это задание из первых изданий. Потому что если сослаться на Страуструпа, то при переносе кода на другие компиляторы бывает важен порядок инициализации, а первые версии не поддерживали его. Хотя, если это все-таки одно из первых изданий, там Страуструп не был еще так чинен и иногда шутил ("напишите программу, чтобы запутать любого. поделитесь с приятелем").

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)