Неининциализированный указатель
От: Max_pv  
Дата: 03.08.03 13:42
Оценка:
class base
{
public:
    int i;
    void fn();
    base();
};
base::base()
{
    cout<<"In base";
}
void base::fn()
{
   cout<<"Super";
}

int main(int argc, char* argv[])
{
    base *f;
    f=NULL;
    f->fn();//все работает
    f->i=5;//ошибка
    getch();
    return 0;
}

Народ, помогите разобраться.
В примере выше я наглядно показал, как можно обратиться к функции не создавая объект класса. но почему так?
Ведь обращение к переменной i вызовет ошибку и это абсолютно верно, а к функции — нет.

Исправлена подсветка синтаксиса. -- ПК.
Re: Неининциализированный указатель
От: WolfHound  
Дата: 03.08.03 16:25
Оценка:
Здравствуйте, Max_pv, Вы писали:

M_>Народ, помогите разобраться.

M_>В примере выше я наглядно показал, как можно обратиться к функции не создавая объект класса. но почему так?
M_>Ведь обращение к переменной i вызовет ошибку и это абсолютно верно, а к функции — нет.
Если сделать функцию виртуальной или обратится из нее к переменным объекта то тоже словишь ошибку. В данном случае нет ошибки только потому что в функции не используется this.
... << RSDN@Home 1.1 alpha 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Неининциализированный указатель
От: Аноним  
Дата: 03.08.03 21:05
Оценка:
Здравствуйте, Max_pv, Вы писали:

M_>В примере выше я наглядно показал, как можно обратиться к функции не создавая объект класса. но почему так?

M_>Ведь обращение к переменной i вызовет ошибку и это абсолютно верно, а к функции — нет.

Всё просто. f->fn(); вызывает функцию в которую первым параметром неявно впихивают указатель f(т.е. в твоем случае NULL). Если ты в теле функции напишешь i = 5; то тем самым ты неявно пишешь f->i = 5 поэтому если f — невалидный(как в твоём примере), то прога рухнет, а если ты не будешь обращаться к переменным класса, то всё пройдёт на ура.
Re: Неининциализированный указатель
От: Андрей Тарасевич Беларусь  
Дата: 03.08.03 23:42
Оценка: 21 (2)
Здравствуйте, Max_pv, Вы писали:

M_>class base

M_>{
M_>public:
M_> int i;
M_> void fn();
M_> base();
M_>};
M_>base::base()
M_>{
M_> cout<<"In base";
M_>}
M_>void base::fn()
M_>{
M_> cout<<"Super";
M_>}

M_>int main(int argc, char* argv[])

M_>{
M_> base *f;
M_> f=NULL;
f->>fn();//все работает
f->>i=5;//ошибка
M_> getch();
M_> return 0;
M_>}
M_>Народ, помогите разобраться.
M_>В примере выше я наглядно показал, как можно обратиться к функции не создавая объект класса. но почему так?

Ничего ты в этом примере наглядно не показал. Попытка обращения к нестатическому члену класса через нулевой указатель приводит в языке С++ к неопределенному поведению. Точка. А что там у тебя случайно получилось никакой роли не играет. С точки зрения языка С++ твой код нелегален и, поэтому, ничего не демонстрирует.

M_>Ведь обращение к переменной i вызовет ошибку и это абсолютно верно, а к функции — нет.


Обращение к нестатическому полю класса приводит к неопределенному поведению, а не "вызывает ошибку". То же самое происходит и при обращении к нестатическому методу класса. А получится ли при этом "ошибка", или покажется, что все нормально стработало — это уже дело десятое.
Best regards,
Андрей Тарасевич
Re: Неининциализированный указатель
От: Plague Россия  
Дата: 04.08.03 09:15
Оценка:
Здравствуйте, Max_pv, Вы писали:


f->>fn();//все работает

f->>i=5;//ошибка

Все дело в механизме реализации классов и вызовах методов...

Так уж случилось, что при вызове метода указатель на класс не используется (т.к. код метода лежит в заранее определенном при компиляции месте, с виртуальными методами отдельный случай), но он неявно передается и виден в методе как this, и обращение к переменым данного класса из метода происходит тоже неявно с использованием this ( например i+=1; в методе тоже самое, что this->i+=1), отсюда выходит, что если бы ты обратился к переменной, то скорее всего возникла бы ошибка (в нашем случае она явно возникнет, т.к. указатель на NULL)

есле методы уже созданы при компиляции и их адрес известен, то с переменными класса все по другому, они находятся непосредственно в экземпляре класса, и для доступа к ним используется (явно или нет) адрес экземпляра класса (вданном случае адре содержит переменная f, а явным доступом к переменной является f->i; )

т.е.:


f->fn(); // функция вызывается и неверный адрес передается в качестве неявного аргумента (this)
f->i=5;  // используется неверный адрес при доступе к переменной класса
... << RSDN@Home 1.1 beta 1 >>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.