Форум программистов, компьютерный форум CyberForum.ru

Глупый вопрос по указателям? - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.67
Alex1234
 Аватар для Alex1234
12 / 12 / 0
Регистрация: 11.02.2011
Сообщений: 55
11.02.2011, 12:08     Глупый вопрос по указателям? #1
Здравствуйте! Подскажите как это работает? Правильно ли я понимаю?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct A
{
};
 
struct B: public A
{
    int var1;
    int var2;
};
 
int main(int argc, char *argv[])
{
    A* x = new A;            //Памяти выделяется на объект от A
    B* y = (B*)x;
    y->var2 = 5;              //Пишет не в свою память?
    ((B*)x)->var2 = 5;      //Это эквивалент?
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.02.2011, 12:08     Глупый вопрос по указателям?
Посмотрите здесь:

простой и глупый вопрос C++
C++ Вопрос по указателям
C++ Вопрос по указателям
C++ Оч глупый вопрос
C++ Глупый вопрос (возведение в квадрат)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
11.02.2011, 12:17     Глупый вопрос по указателям? #2
C++
1
2
3
4
A* x = new A; // Создаётся указатель на объект A (на экземпляр класса A) и по этому указателю выделяется память, достаточная для хранения объекта A
B* y = (B*)x; //Создаётся указатель на тот же объект, причём, через него с этой переменной можно будет работать как с объектом B
y->var = 5; // Пишет в поле var по адресу объекта по адресу x, (или y, так как адреса эти равны), считая его экземпляром класса B
((B*)x)->var = 5; // То же самое.
.

Добавлено через 3 минуты
Это обычное неявное приведение типа, ничего хитрого здесь нет.
Alex1234
 Аватар для Alex1234
12 / 12 / 0
Регистрация: 11.02.2011
Сообщений: 55
11.02.2011, 12:18  [ТС]     Глупый вопрос по указателям? #3
Извиняюсь, правил код.
Выделенной памяти ведь нет для var2 и будет некорректная работа с памятью?
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
11.02.2011, 12:28     Глупый вопрос по указателям? #4
Ты приводишь объект базового класса к производному от него. В производном классе могут быть какие угодно дополнительные поля, каких не было в базовом классе. Но не факт, что выйдешь за память.
C++
1
new A
выделяет память, достаточную, для хранения экземпляра A, но не всегда размером с экземпляр A. Вот если сразу на массив выделять
C++
1
new A[n]
, тогда уже var1 на соседнем элементе этого массива. Но это относится только к полям, но не к методам, так как методам не нужна память в каждом экземпляре.

Добавлено через 1 минуту
Две последние строки и здесь эквивалентны, в первом случае ты просто сохранил указатель
C++
1
(B*)x
в переменной y, а во втором случае работаешь "с колёс".

Добавлено через 1 минуту
А чего ты вообще хочешь? Зарезервировать память под поля производного класса?
Alex1234
 Аватар для Alex1234
12 / 12 / 0
Регистрация: 11.02.2011
Сообщений: 55
11.02.2011, 12:34  [ТС]     Глупый вопрос по указателям? #5
Спасибо большое! Значит правильно понял. Просто запутался. Давно не имел дела с C++. Не понимаю зачем компиляторы такое допускают.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
11.02.2011, 12:50     Глупый вопрос по указателям? #6
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class B
{
 public:
  int a;
  int b;
  void f1();
  void f2();
};
class C
{
 public:
  int a;
  int b;
  voidb f1();
  void f3();
  void f4();
}
И надо выполнить f4 для экземпляра B, причём, оба объекта по смыслу задачи близки, или совпадают, но тебе для каких то целей понадобились раздельные классы. Например, это могут быть комплексные числа в алгебраической и тригонометрической записи. Количество и типы полей совпадают, за память ты не выйдешь, даже если будешь писать/читать, а методы и операторы-члены могут не совпадать. Вот здесь это и пригодится: оба производные от A, но A может быть вообще абстрактным, тогда нельзя создать экземпляр A. Вешать же защиту бесполезно: преобразуют так:
C++
1
2
3
4
5
B *b;
C *c;
void *d;
d=(void *)b;
c=(C *)d;
. Да и бессмысленна такая защита: если уж берёшься писать что либо кроме программ тестового и учебного назначения, то должен понимать, что пишешь, а иначе всё равно найдёшь где сглючить.
Alex1234
 Аватар для Alex1234
12 / 12 / 0
Регистрация: 11.02.2011
Сообщений: 55
11.02.2011, 20:11  [ТС]     Глупый вопрос по указателям? #7
Спасибо! Думаю, еще может пригодится для альтернативной обработки A[n]. Но лишний раз лучше не использовать.

Добавлено через 50 минут
Посоветуйте, что нибудь почитать понятное про размещение объектов в памяти, с разными случаями: типа смещение указателя при приведение типов в случае с множественным наследованием и т.п. Хочу полностью разобраться.

Добавлено через 6 часов 2 минуты
Добрый вечер! У меня еще вопрос по поводу подобных объявлений A* x = new B;
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class A
{
private:
    virtual void virt(){}
};
 
class B: public A
{
public:
    virtual void virt(){}
    int var[100];
};
 
int main(int argc, char *argv[])
{
    A* x = new B;   //Памяти выделили размером A,  
                    //ссылку на vtable получили от B,
                    //да еще и B::virt на которую ссылается
                    //vtable x стал закрытым, 
                    //т.е. x->virt(); не будет работать.
 
}
Правил что-то много получается. Как A* x = new B интерпретировать мозгом?
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
11.02.2011, 20:38     Глупый вопрос по указателям? #8
А что интерпретировать-то? Потомок всегда обладает всеми свойствами предка, т.е. членами-данными и методами. Значит его можно легко усечь до предка.
Alex1234
 Аватар для Alex1234
12 / 12 / 0
Регистрация: 11.02.2011
Сообщений: 55
11.02.2011, 22:22  [ТС]     Глупый вопрос по указателям? #9
Спасибо! Разобрался. А то совсем запутался.
C++
1
A* x = new B;
Это тоже самое, что
C++
1
2
    B* z = new B;
    A* x = z;
Усечение до предка, только память на весь B* z = new B; не выделяется.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
11.02.2011, 22:26     Глупый вопрос по указателям? #10
Да, по такому усечённому указателю мы сможем обратиться только к членам, которые есть в предке.
Alex1234
 Аватар для Alex1234
12 / 12 / 0
Регистрация: 11.02.2011
Сообщений: 55
12.02.2011, 09:44  [ТС]     Глупый вопрос по указателям? #11
Ой. Обшибся. Память все таки выделяется. Че я так запарился на пустом месте.

Добавлено через 11 часов 8 минут
Здравствуйте! Еще вопрос.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class A
{
public:
    virtual ~A(){}
};
 
class B: public A
{
public:
    int var[100000];
    virtual ~B(){}
};
 
 
int main(int argc, char *argv[])
{
    B* z = new B;
    A* x = z;
 
    delete x;
}
С диструктором разобрался. А память выделенная под z освободится при delete x?
Iron Bug
22 / 22 / 0
Регистрация: 06.12.2010
Сообщений: 125
12.02.2011, 13:04     Глупый вопрос по указателям? #12
Цитата Сообщение от Alex1234 Посмотреть сообщение
С диструктором разобрался. А память выделенная под z освободится при delete x?
нет. и в первом вопросе обращение к члену класса B некорректно.

а вообще, сделай явные конструкторы и деструкторы у твоих классов и пиши оттуда сообщения в консоль, например. тогда сам увидишь, что и где вызывается. это самый простой метод, чтобы не задавать кучу вопросов.
Alex1234
 Аватар для Alex1234
12 / 12 / 0
Регистрация: 11.02.2011
Сообщений: 55
12.02.2011, 20:15  [ТС]     Глупый вопрос по указателям? #13
Что от куда вызывается и так понятно, неоднозначности здесь нет, по этому диструктор виртуальный. Не пойму освободится память выделенная под int var[100000];
Iron Bug
22 / 22 / 0
Регистрация: 06.12.2010
Сообщений: 125
12.02.2011, 21:14     Глупый вопрос по указателям? #14
если спрашиваешь - значит, не понятно.
во-первых, ответ однозначный - нет. во-вторых - напиши деструкторы и сам увидишь, что и где. зачем гадать? или читай Страуструпа, до просветления.
вообще, неясно, зачем такие вывихи устраивать. давно придумали смарт-указатели и все, кто не понимает сути работы с конструкторами-деструкторами, счастливы.
Напильнег
480 / 120 / 10
Регистрация: 30.09.2010
Сообщений: 473
12.02.2011, 23:09     Глупый вопрос по указателям? #15
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A
...
};
 
class B: public A
...
};
 
int main(int argc, char *argv[])
{
    B* z = new B;
    A* x = z;
 
    delete x;
}
Цитата Сообщение от Alex1234 Посмотреть сообщение
память выделенная под z освободится при delete x?
Память по переменную z типа (B *), выделяется в стеке и автоматически освобождается по достижению конца операторного блока, и delete x ее никак не касается.

Что же до памяти, указателем на которую проинициализирована z, то она по delete x освобождается корректно (т.е. освобождается sizeof(B) байт) с вызовом деструктора B::~B, т.к. для экземпляров потомков класса, имеющего виртуальные методы, размер экземпляра и указатель на деструктор (и вообще на виртуальные методы) берутся из актуальной таблицы ВМТ, по указателю, хранящемся в экземпляре, а не по типу указателя на класс предка, по которому происходит обращение - собственно, для этого механизм виртуальных методов и создавался.
Alex1234
 Аватар для Alex1234
12 / 12 / 0
Регистрация: 11.02.2011
Сообщений: 55
12.02.2011, 23:24  [ТС]     Глупый вопрос по указателям? #16
Еще раз.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class A
{
public:
    virtual ~A(){}
};
 
class B: public A
{
public:
    B(){var2 = new int[10000];}
    int var[100000];
    int* var2;
    virtual ~B(){ delete var2; }
};
 
int main(int argc, char *argv[])
{
    B* z = new B;
    A* x = z;
 
    delete x;         //По указателю в vtable будет вызван
                      //деструктор B::~B(). Чего тут понимать,
                      //на то A::~A() и виртуальный,
                      //в данном случае для освобождения 
                      //памяти от var2.
    
    z->var[500] = 3;  //Мне интересно что будет в этом случае?
}
Лаподь
Заблокирован
13.02.2011, 00:33     Глупый вопрос по указателям? #17
Цитата Сообщение от Alex1234 Посмотреть сообщение
C++
1
2
3
4
5
delete x;   //По указателю в vtable будет вызван 
            //деструктор B::~B(). Чего тут понимать, 
            //на то A::~A() и виртуальный, 
            //в данном случае для освобождения 
            //памяти от var2.
А также будет освобождена память, выделенная ранее по new B для экземпляра класса B (для его не динамических полей).

Цитата Сообщение от Alex1234 Посмотреть сообщение
C++
1
z->var[500] = 3;   //Мне интересно что будет в этом случае?
Обращение к свободной (не помеченной как используемой программой) памяти (если какой подпроцесс не успеет к тому времени занять) с непредсказуемыми последствиями.
Alex1234
 Аватар для Alex1234
12 / 12 / 0
Регистрация: 11.02.2011
Сообщений: 55
13.02.2011, 21:52  [ТС]     Глупый вопрос по указателям? #18
Спасибо большое за ответ!!! А то я совсем запарился.

Добавлено через 9 минут
Извиняюсь Напильнег, пост не увидел. А почему память по переменную z типа (B *), выделяется в стеке? Я думал в куче.

Добавлено через 19 часов 47 минут
Добрый вечер! У меня еще вопрос, уже по строкам.
C++
1
2
3
4
5
6
7
8
9
10
int main(int argc, char *argv[])
{
    char* str = "Hello world";  //т.е. const char* str;
                                  //но много где видел и такое.
    
    str[0]   = 'M';    //Компилятор без разговоров проглатывает,
    *(str+2) = 'r';    //но ничего не пишет в строку.
    
    cout << str;       //Выводит Hello world 
}
Происходит ли запись какой нибудь памяти str[0] = 'M'; *(str+2) = 'r'; или эти строки не выполняются?
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
13.02.2011, 21:55     Глупый вопрос по указателям? #19
У меня программа зависает при попытке выполнить программу. При комментировании 7 и 8 строк - отрабатывает. Но делать так всё равно нехорошо. Нужно выделить память под str, а потом уже что-то в неё писать.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.02.2011, 22:03     Глупый вопрос по указателям?
Еще ссылки по теме:

Глупый вопрос по шаблонам C++
C++ Глупый вопрос про наследование
Извините за глупый вопрос. C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4237 / 2770 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
13.02.2011, 22:03     Глупый вопрос по указателям? #20
По идеи такое не должно работать. Но вот последний gcc позволяет такое делать (точнее именно так я не пробовал, но константные строки менял)), что по-моему не есть правильно.
Yandex
Объявления
13.02.2011, 22:03     Глупый вопрос по указателям?
Ответ Создать тему
Опции темы

Текущее время: 18:06. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru