Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: Конструктор/Деструктор - когда вызывать?  (Прочитано 41665 раз)
0 Пользователей и 10 Гостей смотрят эту тему.
EXE
Гость
« : 10-11-2003 08:15 » 

Люди добрые помогите! Ситуация следующая:
Имеется клас A.

class A
{
   private:
   ...
   ...
   ...
   public:
        ...
        ...
        ...
        A(int);
        ~A();
};

//конструктор
void A::A(int param)
{
   ...
   ...
   ...
}

//деструктор
void A::~A()
{
   ...
   ...
   ...
}

Перед main объявляю экземпляр класса:
A cl(10);

В книжке по C++ я прочитал, что конструктор вызывается автоматически при объявлении переменной имеющей тип класса.
Если конструктор не был реализован в объявлении класс, то компилятор соберёт свой дефолтовый конструктор. Это вроде бы ясно.
Деструктор вызывается автоматически в следующих случаях:
1. Когда переменная-класс покидает область видимости в которой она объявлена;
2. Когда вызывается delete с указателем на класс в качестве параметра.

Из вышесказанного следует, что деструктор вообще вызывать не нужно!!! Т.е. компилятор позаботится об этом сам!
Но как быть, если до конца области видимости ещё далеко, а экземпляр класса мне уже не нужен и я хочу освободить
занимаемуею объектом память вызвав деструктор (delete &cl)?
Я делал так:
delete(&cl);
И вот так:
cl.~A();

В любом случае возникает ошибка - и это логично - ведь сначала я разрушаю объект деструктором, а потом деструктор
вызывается автоматически(из кода который вставил компилятор), а объекта то в памяти уже нет - получаю access violation.

Буду благодарен если Вы объясните мне что я делаю не так? Я повторю вопрос...

Но как быть, если до конца области видимости ещё далеко, а экземпляр класса мне уже не нужен и я хочу освободить
занимаемуею объектом память вызвав деструктор (delete &cl)?
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #1 : 10-11-2003 08:28 » 

Тебя спасет или использование стандартного распределителя памяти
A* a= new A(...);
.......
delete a;

Или создание собственного распределителя - void* operator new(size_t s, ...) и парного ему void operator delete(size_t s); Но это тема сложная и большая, как говорится "Неисчерпаема как атом"(В. И. Ульянов). Используй стандартный.

Вызывать самостоятельно деструктор для стековых объектов(как это сделал ты) запрещено. И никогда не вызывай delete для стековых объектов! Он вызывается для объектов с динамически распределенной памятью и является парным к new.
Записан
EXE
Гость
« Ответ #2 : 10-11-2003 08:47 » 

Понял - спасибо!!!
А вот так можно?

A* a = (A*)malloc( sizeof(  A(10) ) );
...
...
...
free(a);
...
...
...
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #3 : 10-11-2003 09:03 » 

Цитата

А вот так можно?

A* a = (A*)malloc( sizeof( A(10) ) );
...
...
...
free(a);


НЕТ!Ты путаешь С и C++, а также стековые, статические и динамические объекты. sizeof( A(10) )- это вобще не откомпилируется. А кто конструктор вызовет?

Вот так еще можно поробовать.
void* pa = malloc( sizeof( A(10) ) );
А* a=new(pa) A(10);
...
...
...
a.~A();
free(pa);
Записан
EXE
Гость
« Ответ #4 : 10-11-2003 09:11 » 

SlavaI - Большое СПАСИБО - буду читать дальше )))
Записан
Migmile
Помогающий

ru
Offline Offline

« Ответ #5 : 11-11-2003 06:58 » 

Цитата

void* pa = malloc( sizeof( A(10) ) );
А* a=new(pa) A(10);
...
...
...
a.~A();
free(pa);

А вот это уже через-чур Отлично
Все равно new вызывает под собой malloc по умолчанию (по крайней мере в VC)
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #6 : 11-11-2003 08:10 » 

Цитата
А вот это уже через-чур  
Все равно new вызывает под собой malloc по умолчанию (по крайней мере в VC)

Читай стандарт. А то ты тоже не понимаешь смысла new, воспринимая его только как malloc. Ничего оператор void* operator new(size_t sz, void* pl) не вызывает он просто возвращает переданный ему указатель на память а компилятор вызывает конструктор, инициализируя этот кусок памяти. Это надо только для инициализации уже выделенной области памяти.
 вот как он объявлен в VC

Код:
inline void *__cdecl operator new(size_t, void *_P)
        {return (_P); }

Вот тебе програмка, компильни ее

Код:
#include <new.h>
#include <iostream.h>
#include <stdlib.h>

class A
{
public:
int a;
A(int i){a=i;};
~A()|";
};

int _tmain(int argc, _TCHAR* argv[])
{
   void* pa = malloc(sizeof(A));
   A* a=new(pa) A(10);

   cout<<a->a<<endl;

  a->~A();
  free(pa);
  return 0;
}

Еще раз повторю- не путайте С и C++.
« Последнее редактирование: 20-11-2007 19:14 от Алексей1153++ » Записан
Migmile
Помогающий

ru
Offline Offline

« Ответ #7 : 11-11-2003 08:28 » 

SlavaI, это я прекрасно понимаю, просто сначала выделять память alloc-ом, а затем размещать на ней объект не часто необходимо!
А "обычный" new выглядит примерно так:
void * operator new( size_t cb )
{
        void *res = _nh_malloc( cb, 1 );
        RTCCALLBACK(_RTC_Allocate_hook, (res, cb, 0));
        return res;
}
(VC7 CRT)
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #8 : 11-11-2003 08:30 » 

Цитата

SlavaI, это я прекрасно понимаю, просто сначала выделять память alloc-ом, а затем размещать на ней объект не часто необходимо!
А "обычный" new выглядит примерно так:
void * operator new( size_t cb )
{
void *res = _nh_malloc( cb, 1 );
RTCCALLBACK(_RTC_Allocate_hook, (res, cb, 0));
return res;
}


Если ты это понимаешь, то зачем написал свое сообшение? Человек спросил- можно ли так, я ему ответил, что можно, но надо как-то вызвать конструктор, а компилятор вызовет конструктор только для new, но не malloc. Тот new не вызывает malloc.
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #9 : 11-11-2003 08:34 » 

Migmile, не сбивай людей с толку. Вопрос задан в "С м С++", а не "С++ для ОС".
Слава и отвечает по стандарту.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Migmile
Помогающий

ru
Offline Offline

« Ответ #10 : 11-11-2003 08:39 » 

Ладно, ладно - утоптали!
Просто чем проще ответ - тем он понятнее Улыбаюсь
Записан
Fatal Error
Гость
« Ответ #11 : 12-11-2003 06:32 » 

А почему все забывают о списке инициализации членов :?: Писать корректнее надо  так
Код:
A(int i)  :  a(i) {}; 
Плюс еще вы выполняется быстрее.

Напрямую вызывать деструктор можно и для стековой переменной - должно работать, у меня проблем не было.
« Последнее редактирование: 20-11-2007 19:15 от Алексей1153++ » Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #12 : 12-11-2003 07:10 » 

Цитата

Писать корректнее надо так Код:
A(int i)  :  a(i) {};


Кто тебе сказал, что это корректнее, можно писать и так и как я, никакой ошибки или неточности нет. В моем случае сначала вызовется конструктор по умолчанию, а потом B& operator=(const B&), но оптимизирующие компиляторы для встроенных типов не делают разницы между твоей и моей записью.

Цитата

Напрямую вызывать деструктор можно и для стековой переменной - должно работать, у меня проблем не было.


Ну вот только не надо- я пробовал! Ты сказал абсолютно неверную вещь. Нельзя, и не спорь. Этот деструктор второй раз вызовут при уходе из области видимости, это жестко зашито в код компилятором. То что программа не упала ничего не значит. Деструктор не освобождает память, выделенную под объект класса, тем более стековую память. Поэтому повторный вызов не дал никакого эффекта, а вот попробуй в деструкторе освобождать память, выделенную при помощи new в конструкторе для члена класса. А потом вызови деструктор для стековой переменной. Для чистоты измени указатель в деструкторе. Получишь по рукам! Система посмеется над таким способом.

Говоришь пробовал. Попробуй это-

class D
{
   int* pi;
public:
   D(){ pi = (int*)new int[10]; };
   ~D(){ delete[] pi; pi=(int*)0x1000 ; };
};

int _tmain(int argc, _TCHAR* argv[])
{
   D d;
   d.~D();
}
Записан
Fatal Error
Гость
« Ответ #13 : 12-11-2003 15:40 » 

SlavaI <<[/b] А если не встроенный тип, все-таки мне кажется, что так писать более красиво и читаемо... имхо.

А если делать так, то проблем не будет:
Код:
class D 
{
int* pi;
public:
D(){ pi = (int*)new int[10]; };
~D()| delete[] pi; pi = NULL; };
};

int _tmain(int argc, _TCHAR* argv[])
{
D d;
d.~D();
}

Вообще можно в функции дополнительный блок делать и там писать нужную переменную и при выходе из блока она удалиться сама (если стёковая):

Код:
int BIG_f() 
{
 {
  D d;
  //..............
 }
 // тут d уже нету :(
 //.............
}
« Последнее редактирование: 20-11-2007 19:18 от Алексей1153++ » Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #14 : 13-11-2003 06:18 » 

Цитата
А если делать так, то проблем не будет:
Код:
class D
{
int* pi;
public:
D(){ pi = (int*)new int[10]; };
~D(){ delete[] pi; pi = NULL; };
};

int _tmain(int argc, _TCHAR* argv[])
{
D d;
d.~D();
}

Ты хоть понимаешь почему тут проблем нет? Потому что delete при получении нулевого указателя ничего не делает.
Ты что действительно не понимаешь, что вызываешь деструктор два раза? И пытаешься доказать что самому вызывать деструктор для стековой переменной это правильно и очень хорошо.
А если класс управляет станком и конструктор передвигает резец на n миллиметров, а деструктор отодвигает обратно на n миллиметров, так вот у тебя отодвинется на 2*n миллиметров, представляешь что он у тебя выточит. Хорошо если станком, а не самолетом, а то закрылки вместо F градусов на 2*F отвернутся, такая радость пилоту будет, хорошо если самолет военный и есть система катапультации, но вот если и эта система также написана, жалко пилота.

Насладись еще раз этим шедевром

Код:
#include <iostream.h>

class D
{
int* pi;
float& grad;
public:
D(float& g):grad(g){
            pi = (int*)new int[10];
            cout<< "turn flap"<<endl;
            grad+=10;}

~D(){
      delete[] pi;
      pi = NULL;
      cout<< "return flap"<<endl;
      grad -= 10;
      if(grad<0)
  {
  cout<<"Bye-bye guy!"<<endl;
  }}
};

int _tmain(int argc, _TCHAR* argv[])
{
float grad=0;
D d(grad);
d.~D();
}
« Последнее редактирование: 20-11-2007 19:22 от Алексей1153++ » Записан
Sashok
Молодой специалист

us
Offline Offline
Пол: Мужской

« Ответ #15 : 13-11-2003 15:31 » 

Fatal Error, возьми, да поставь в деструктор вывод на экран - четко увидишь, что у тебя происходит.
Записан

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

ua
Offline Offline

« Ответ #16 : 13-11-2003 18:48 » 

Цитата

Этот деструктор второй раз вызовут при уходе из области видимости, это жестко зашито в код компилятором.

Наверное при окончании жизни объекта. Все таки область видимости и время жизни разные понятия. (Например static объекты).
Записан
Sashok
Молодой специалист

us
Offline Offline
Пол: Мужской

« Ответ #17 : 13-11-2003 19:27 » 

Цитата: ysv_
Цитата

Этот деструктор второй раз вызовут при уходе из области видимости, это жестко зашито в код компилятором.

Наверное при окончании жизни объекта. Все таки область видимости и время жизни разные понятия. (Например static объекты).
Безусловно!
Записан

Если бы окружающие нас объекты содержали столько же ошибок, сколько программы, цивилизация обрушилась бы от первого порыва ветра...
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #18 : 13-11-2003 20:01 » 

ysv_, смотря где был произведен вызов конструктора...
Вернее даже не так - где был объявлен экземпляр объекта...
Если я внутри оъекта внутри одной из его функций объявлю класс, то как только я выйду за пределы ее, то именно это и произойдет.
Записан

А птичку нашу прошу не обижать!!!
ysv_
Помогающий

ua
Offline Offline

« Ответ #19 : 13-11-2003 20:29 » 

Гром, моя твоя не понимай.
Вызов деструктора всегда происходит при окончании жизни объекта. Просто для автоматических объектов уход из области видимости совпадает со времен окончания жизни.
А насчет твоего утверждения, как я его понял, вот код:

#include <iostream>

class A
{
  public:
  A() {std::cout<<"A\n";}
  ~A() {std::cout<<"~A\n";}

  void func()
  {
    static class B
    {
      public:
        B() {std::cout<<"B\n";}
        ~B() {std::cout<<"~B\n";}
    } b;
  }
};

int main()
{
  A a;
  a.func();
  return 1;
}

Вывод:
A
B
~A
~B

Т.е. А умирает при выходе из зоны видимости, а B - при завершении работы программы.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #20 : 13-11-2003 20:59 » 

Ты не понял...

#include <iostream>
class A
{
public:
A() {std::cout<<"A\n";}
~A() {std::cout<<"~A\n";}
}

class B
{
public:
B() {std::cout<<"B\n";}
~B() {std::cout<<"~B\n";}
void func();

}



void B::func()
{
A a;
}


int main()
{
B b;
b.func();
return 1;
}

Я это имел ввиду - компайлера нет - сдох надо переставлять насколько я понимаю - проверб пожалуйста, вывод будет такой...

B
A
~A
~B
Записан

А птичку нашу прошу не обижать!!!
Sashok
Молодой специалист

us
Offline Offline
Пол: Мужской

« Ответ #21 : 13-11-2003 23:44 » 

Гром, так у тебя же оба объекта - auto, а у ysv_ объект a - auto, a объект b - static.
Записан

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

ru
Offline Offline

« Ответ #22 : 14-11-2003 06:25 » 

Цитата

Наверное при окончании жизни объекта. Все таки область видимости и время жизни разные понятия. (Например static объекты).


Ну начались придирки. Ты видел статические стековые объекты? А мы говорили только о стековых объектах.

class A {};

void foo()
{
     static A a;// вовсе не означает что он в стеке.
}
Записан
NetRaider
Гость
« Ответ #23 : 14-11-2003 07:23 » 

Цитата

Вызывать самостоятельно деструктор для стековых объектов(как это сделал ты) запрещено.

 
Цитата

Цитата

Напрямую вызывать деструктор можно и для стековой переменной - должно работать, у меня проблем не было.

 
Ну вот только не надо- я пробовал! Ты сказал абсолютно неверную вещь. Нельзя, и не спорь.


Такие категоричные ответы неплохо бы аргументировать.

После окончания времени жизни объектов(к этому приводит вызов деструктора первый раз) запрещено вызывать не только деструкторы:

12.4.14 Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the
destructor is invoked for an object whose lifetime has ended ( 3.8 )
[Example: if the destructor for an automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily invoke implicit destruction of the object, the behavior is undefined.]

но и любые non-static функции-члены (3.8.6).
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #24 : 14-11-2003 08:04 » new

Цитата

Такие категоричные ответы неплохо бы аргументировать.


А что, приведенная мной аргументация недостаточна, про двойной вызов деструктора? Обязательно привести выдержку из стандарта? Или ответ неправилен? Тут только два варианта- или можно или нет.

Цитата

После окончания времени жизни объектов(к этому приводит вызов деструктора первый раз) запрещено вызывать не только деструкторы:


Как бы попроще сказать? -Чего вызывать? Нет объекта. От чего вызывать?
Все эти феньки с возможностью вызова второй раз деструктора и другие аномалии возможны только потому, что не затирается память, которую занимал объект и его структуры сохраняются, поэтому некоторые и умудряются что-то вызвать и даже получить какой-то результат. Так что это аномалии, не более того. И даже не стоит употреблять фразу "запрещено вызывать не только деструкторы", нечего вызывать на несуществующий объект.
Записан
NetRaider
Гость
« Ответ #25 : 14-11-2003 08:46 » 

Цитата
А что, приведенная мной аргументация недостаточна, про двойной вызов деструктора? Обязательно привести выдержку из стандарта? Или ответ неправилен? Тут только два варианта- или можно или нет.

Недостаточна, поскольку основана на примерах, которые достаточно сложно придумать на все случаи. То есть ты говоришь что нельзя, подтверждаешь это конкретным примером, но некоторые придумав при что-то свое, вроде этого

Код:
class D 
{
int* pi;
public:
D(){ pi = (int*)new int[10]; };
~D(){ delete[] pi; pi = NULL; };
};

int _tmain(int argc, _TCHAR* argv[])
{
D d;
d.~D();
}

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

Цитата
Все эти феньки с возможностью вызова второй раз деструктора и другие аномалии возможны только потому, что не затирается память, которую занимал объект и его структуры сохраняются, поэтому некоторые и умудряются что-то вызвать и даже получить какой-то результат. Так что это аномалии, не более того. И даже не стоит употреблять фразу "запрещено вызывать не только деструкторы", нечего вызывать на несуществующий объект.

Где написано о том, что после вызова деструктора структуры сохраняются ? Эта особенность конкретных компиляторов, но не языка. Содержимое объекта после вызова деструктора неопределено. Все. Любые вызовы не статических функций от имени этого объекта приводят не к "аномалиям" а к неопределенному поведению, которое возникает в первую очередь от того, что не известно содержимое памяти объекта. На одном компиляторе содержимое может оставаться неизменным, на другом, например обнуляться. Но в рамках языка поведение в таких случаях является неопределенным.
« Последнее редактирование: 20-11-2007 19:29 от Алексей1153++ » Записан
Fatal Error
Гость
« Ответ #26 : 15-11-2003 15:22 » 

SlavaI  <<[/b] Спокойно, я понимаю в чем прикол и что деструктор дважды вызывается в данном случае. Но все-таки ручной вызов может быть полезным в некоторых случаях и вообще у меня привычка всем указателям после использование NULL присваивать.
Записан
Xeysan
Гость
« Ответ #27 : 16-11-2003 12:54 » 

Будет использоваться книга Бьерн Страуструп "Язык программирования С++, специальное издание".

Выдержки я набивать не буду, просто поставлю, какие главы смотреть.

2 Migmile
Цитата

void * operator new( size_t cb )
{
void *res = _nh_malloc( cb, 1 );
RTCCALLBACK(_RTC_Allocate_hook, (res, cb, 0));
return res;
}


Герб Саттер "Решение сложных задач на С++" ( C++ In-Depth ):
Цитата

Достаточно важно различать кучу и свободную память, поскольку стандарт умышленно оставляет вопрос о взаимоотношении этих областей памяти открытым. Например, при освобождении памяти посредством ::operator delete последнее замечание в разделе 18.4.1.1 стандарта С++ гласит следующее.
Цитата

Не определено, при каких условиях часть или вся освобожденная таким образом память будет выделена последующим вызовом operator new или любой из функций calloc, malloc, realloc, объявленным в <cstdlib>


Кроме того, не определено, должны ли операторы new/delete быть реализованы посредством malloc/free в конкретном компиляторе. Однако malloc/free не должны быть реализованы посредством new/delete в соотв. с разделами 20.4.6.3-4 стандарта.
Цитата

Функция calloc(), malloc() и realloc не должны пытаться выделить память, используя вызов ::operator new.

Цитата

Функция free() не должна пытаться освоб. память, используя вызов ::operator delete.



-------

Цитата

Писать корректнее надо так Код:
A(int i) : a(i) {};

Кто тебе сказал, что это корректнее, можно писать и так и как я, никакой ошибки или неточности

нет. В моем случае сначала вызовется конструктор по умолчанию, а потом B& operator=(const B&),

но оптимизирующие компиляторы для встроенных типов не делают разницы между твоей и моей записью.

 
БС -> 10.4.6.1 и не надо вспоминать оптимиз. компиляторы...
-------
Цитата

Все эти феньки с возможностью вызова второй раз деструктора и другие аномалии возможны только

потому, что не затирается память, которую занимал объект и его структуры сохраняются, поэтому

некоторые и умудряются что-то вызвать и даже получить какой-то результат. Так что это аномалии,

не более того. И даже не стоит употреблять фразу "запрещено вызывать не только деструкторы",

нечего вызывать на несуществующий объект.


Попробуй так Улыбаюсь
class A {
public:
void   f() { std::cout<<"Hello"; }
};
...
((A*)0)->f();

В msvc 7.0 вполне работает... Улыбаюсь ( нет обращ. к this )
-------
Насчет явного вызова деструктора:
БС -> 10.4.1 / 10.4.11

зы Литература серьезная, поэтому бейте меня стандартом Улыбаюсь
Записан
NetRaider
Гость
« Ответ #28 : 17-11-2003 02:15 » 

Цитата
Попробуй так  
class A {
public:
void f() { std::cout<<"Hello"; }
};
...
((A*)0)->f();

В msvc 7.0 вполне работает...  ( нет обращ. к this )

Во-первых:
Цитата
5.2.5
A postfix expression followed by a dot . or an arrow ­>,
optionally followed by the keyword template
(14.8.1), and then followed by an idexpression,
is a postfix expression. The postfix expression before the
dot or arrow is evaluated;

То есть выражение, стоящее слева от '.' или '->' при доступе к члену класса -функции(и статической в том числе) или полю, обязательно вычисляется. Вычисление этого выражения приводит к разыменованию используемого в нем указателя.

Что, в свою очередь, приводит к:

Цитата
1.9 Program execution (intro.execution)
4 Certain other operations are described in this International Standard as undefined (for example, the effect of dereferencing the null pointer).

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

Тем не менее, следующий код не порождает неопределенного поведения:

Код:
#include <iostream>
#include <typeinfo>
 
struct A {
    void f() { std::cout<< "Hello\n"; }
};


int main()
{
    std::cout << typeid(((A*)0)->f).name();
    return 0;
}
Так как в этом случае параметр 'typeid' не вычисляется(5.2.8/3).
« Последнее редактирование: 20-11-2007 19:30 от Алексей1153++ » Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #29 : 17-11-2003 06:16 » 

Xeysan, вот твой код.

Цитата

class A {
public:
void f() { std::cout<<"Hello"; }
};
...
((A*)0)->f();


Сразу скажу, что this там используется и в ф-цию передается- он просто NULL равен. Ты же не пытаешься получить доступ к нестатическим членам класса, поэтому и работает. А ф-ции всегда передается столько параметров, сколько надо.
 Не знаю к чему ты его привел, но отвечу - если ты так любишь цитаты приводить, что данный код приведен в книге B. Stroustrup "The design and evolution of C++" еще в 1994 году, там же он обозван "непереносимой конструкцией" и "бомбой замедленного действия" и объяснено почему(не только из-за разименования).

Цитата

Литература серьезная, поэтому бейте меня стандартом


Так,NetRaider в тебя стандартом запустил уже. А я в тебя кидаю книжкой B. Stroustrup "The design and evolution of C++", но тебе повезло- она нетолстая.
Записан
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines