На информационном ресурсе применяются cookie-файлы. Оставаясь на сайте, вы подтверждаете свое согласие на их использование.
Наследование
3082
26
Есть класс Base, от которого наследуются классы Child1, Child2, Child3. Пусть экземпляры дочерних классов описывают свойства айтемов какого-то меню, которые как-то выбираются пользователем.
Вопрос.
Что происходит с памятью в случае нижеприведенной реализации?
// ----------------------
void main(void)
{
Base *obj;
...
switch(int i)
{
case 1: obj = new Child1; break;
case 2: obj = new Child2; break;
case 3: obj = new Child3; break;
}
obj->show();
}
// ---------------------
Каким образом выделяется память под объекты, определяемые пользователем? Грубо говоря, если
передать в наш switch() последовательно 1, 2, 3, 2, 1, 2 или что-нить в этом роде, выделится память для всех объектов или же каждый раз объект будет переписываться в память начиная с позиции, на которую указвыает *obj?
Вопрос.
Что происходит с памятью в случае нижеприведенной реализации?
// ----------------------
void main(void)
{
Base *obj;
...
switch(int i)
{
case 1: obj = new Child1; break;
case 2: obj = new Child2; break;
case 3: obj = new Child3; break;
}
obj->show();
}
// ---------------------
Каким образом выделяется память под объекты, определяемые пользователем? Грубо говоря, если
передать в наш switch() последовательно 1, 2, 3, 2, 1, 2 или что-нить в этом роде, выделится память для всех объектов или же каждый раз объект будет переписываться в память начиная с позиции, на которую указвыает *obj?
Каждый раз натыкаясь на new программа будет создавать новый обьект указанного класса, переопределяя значение указателя obj. По-моему так.
craxx
рыжий котэ
Выделится память для всех объектов, но доступ будет только к последнему, а остальные будут болтаться в динамической памяти мусором. Самый простой выход - использовать массив указателей.
Электроник
guru
А ещё можно создать просто статическое меню. (не путать с заболеванием) 

Поручик Голицын
шатун сибирский обыкновенный
Думаю, что если бы человека устраивало статическое, то он не парился бы с динамическим....

если
передать в наш switch() последовательно 1, 2, 3, 2, 1, 2 или что-нить в этом роде, выделится память для всех объектов или же каждый раз объект будет переписываться в память начиная с позиции, на которую указвыает *obj?
Объекты будут каждый раз создаваться заново, а значение obj меняться. Чтобы не было утечек памяти (не Java все-таки), лучше написать что-то вроде:
void main(void)
{
Base *obj = NULL;
...
Child1 *child1 = NULL;
Child2 *child2 = NULL;
Child3 *child3 = NULL;
switch(i)
{
case 1:
if (!child1) child1 = new Child1;
obj = child1;
break;
case 2:
if (!child2) child2 = new Child2;
obj = child2;
break;
case 3:
if (!child3) child3 = new Child3;
obj = child3;
break;
}
if (obj) obj->show();
delete child1;
delete child2;
delete child3;
....
}
Тогда экземпляры menuitem'ов не будут дублироваться и не будут теряться ссылки на них.
передать в наш switch() последовательно 1, 2, 3, 2, 1, 2 или что-нить в этом роде, выделится память для всех объектов или же каждый раз объект будет переписываться в память начиная с позиции, на которую указвыает *obj?
Объекты будут каждый раз создаваться заново, а значение obj меняться. Чтобы не было утечек памяти (не Java все-таки), лучше написать что-то вроде:
void main(void)
{
Base *obj = NULL;
...
Child1 *child1 = NULL;
Child2 *child2 = NULL;
Child3 *child3 = NULL;
switch(i)
{
case 1:
if (!child1) child1 = new Child1;
obj = child1;
break;
case 2:
if (!child2) child2 = new Child2;
obj = child2;
break;
case 3:
if (!child3) child3 = new Child3;
obj = child3;
break;
}
if (obj) obj->show();
delete child1;
delete child2;
delete child3;
....
}
Тогда экземпляры menuitem'ов не будут дублироваться и не будут теряться ссылки на них.
Egor_M
experienced
Мертвая птица тебе поможет.
На сколько я помню, там достаточно хорошо описано что делает new и почему после него нужно делать delete, зачем нужны виртуальные диструкторы и т.д.
На сколько я помню, там достаточно хорошо описано что делает new и почему после него нужно делать delete, зачем нужны виртуальные диструкторы и т.д.
Сейчас читают
Общие черты характера у людей с одним именем
30175
227
Зачем нужен муж?
33050
257
Помогите разобраться
19706
183
Объекты будут каждый раз создаваться заново, а значение obj меняться. Чтобы не было утечек памяти (не Java все-таки), лучше написать что-то вроде:Давно не трогал с++, помоему там проще сделать у наследников виртуальный диструктор и код тогда будет типа такого
......
void main(void)
{
Base *obj = NULL;
...
switch(i)
{
case 1:
obj = new child1;
break;
case 2:
obj = new child2;
break;
case 3:
obj = new child3;
break;
}
if (obj) obj->show();
delete obj;
....
}
помоему там еще у всех наследников должен быть виртуальный диструктор.
Ессно.
Ессно.
поздно уже, не внимательно прочитал код.
исправил пост.
зачем там городить огороды с 3-мя указателями, если достаточно 1 -го указателя на Base и виртуальных деструкторов в потомках.
исправил пост.
зачем там городить огороды с 3-мя указателями, если достаточно 1 -го указателя на Base и виртуальных деструкторов в потомках.
зачем там городить огороды с 3-мя указателями, если достаточно 1 -го указателя на Base и виртуальных деструкторов в потомках.
Ну, код там вообще сам по себе странный, задумка автора слишком не ясна, но можно, конечно, добавить всего одну строку после вызова ->show():
delete obj;
чтобы удалять использованный экземпляр объекта.
Ну, код там вообще сам по себе странный, задумка автора слишком не ясна, но можно, конечно, добавить всего одну строку после вызова ->show():
delete obj;
чтобы удалять использованный экземпляр объекта.
Та-ак.. вроде кое-что начинает проясняться.
Только вот виртуальный деструктор - это что?
Тот самый delete obj, выполняющийся по завершении работы функции?
А если у меня этих функций много? Более того, приложение виндовое, и в нем присутствует необходимость использования свойств объекта (одного из Child'ов) при нажатии на кнопку.
Грубо говоря, нажал одну кнопку - пускается одна функция объекта, вторую - другая.
То есть delete памяти под объект представляется возможным сделать только в момент выделения памяти под другой (при выборе очередного айтема пользователем).
Разумно ли нижеследующее?
void main(void)
{
Base *obj = NULL;
...
switch(int i)
{
delete obj; // пользуемся тем, что указатель остается
case 1: obj = new Child1; break;
case 2: obj = new Child2; break;
case 3: obj = new Child3; break;
}
obj->show();
}
А мертвая птица - она что-то пока мне кажется пособием для каких-то иноземных существ.
Только вот виртуальный деструктор - это что?
Тот самый delete obj, выполняющийся по завершении работы функции?
А если у меня этих функций много? Более того, приложение виндовое, и в нем присутствует необходимость использования свойств объекта (одного из Child'ов) при нажатии на кнопку.
Грубо говоря, нажал одну кнопку - пускается одна функция объекта, вторую - другая.
То есть delete памяти под объект представляется возможным сделать только в момент выделения памяти под другой (при выборе очередного айтема пользователем).
Разумно ли нижеследующее?
void main(void)
{
Base *obj = NULL;
...
switch(int i)
{
delete obj; // пользуемся тем, что указатель остается
case 1: obj = new Child1; break;
case 2: obj = new Child2; break;
case 3: obj = new Child3; break;
}
obj->show();
}
А мертвая птица - она что-то пока мне кажется пособием для каких-то иноземных существ.
craxx
рыжий котэ
delete obj; // пользуемся тем, что указатель остаетсяНеа не правильно...
case 1: obj = new Child1; break;
case 2: obj = new Child2; break;
case 3: obj = new Child3; break;
Как же указатель у тебя остался, если ты в начале функции присвоил его равным NULL? Да и потом obj - это локальная переменная.
Еще раз повторю: используй массив указателей, это проще всего.
craxx
рыжий котэ
Ну примерно так:
void main(void)
{
int i;
Base *obj[3] ={ NULL,NULL,NULL);
...
switch(i)
{
case 1: obj[i] = new Child1; break;
case 2: obj[i] = new Child2; break;
case 3: obj[i] = new Child3; break;
}
//какие-то действия
obj[i]->show();
delete obj[i];
}
Или что-то похожее...
void main(void)
{
int i;
Base *obj[3] ={ NULL,NULL,NULL);
...
switch(i)
{
case 1: obj[i] = new Child1; break;
case 2: obj[i] = new Child2; break;
case 3: obj[i] = new Child3; break;
}
//какие-то действия
obj[i]->show();
delete obj[i];
}
Или что-то похожее...
1. В предложенном Вами варианте придется делать нечто вроде obj[0]->show();
Узнать, каким вышел объект из свитча можно только, таская за ним какое-то int'овое значение значение (определяемое, кстати, в том же свитче) для использования в виде
obj[ i ]->show();
Но проблема в том, что я могу делать delete только на этапе выделения памяти для другого объекта.
2. Такой еще вопрос.
В чем разница между
Base *obj[3] ={ NULL,NULL,NULL };
и
Base *obj[3];
Идентичны ли эти определения? Ведь в каждом из случаев создается массив указателей, указывающих ни на что.
Узнать, каким вышел объект из свитча можно только, таская за ним какое-то int'овое значение значение (определяемое, кстати, в том же свитче) для использования в виде
obj[ i ]->show();
Но проблема в том, что я могу делать delete только на этапе выделения памяти для другого объекта.
2. Такой еще вопрос.
В чем разница между
Base *obj[3] ={ NULL,NULL,NULL };
и
Base *obj[3];
Идентичны ли эти определения? Ведь в каждом из случаев создается массив указателей, указывающих ни на что.
craxx
рыжий котэ
Определения не идентичны, во втором случае может быть любое значение, т.к. просто резервируется память в стеке.
В принципе массив можно стделать динамическим или вобще вектором, а память освобождать в кнце программы.
В принципе массив можно стделать динамическим или вобще вектором, а память освобождать в кнце программы.
Egor_M
experienced
А мертвая птица - она что-то пока мне кажется пособием для каких-то иноземных существ.Книга такая,
Страуструп, Язык С++ , я читал 3-е издание, там все было достаточно понятно описано.
Диструктор - функция такая, которая вызывается при уничтожении объекта.
Если диструктор не виртуальный то для того, что бы код
Base *a=new Child1 ;
delete a;
отрабатывал коректно, т.е. уничтожел в памяти именно объект класса Child1 а не объект класса Base для каждого наследника нужно переопределять оператор delete, что выглядит убого, проще создать пусть даже пустой виртуальный диструктор.
Блин, ты бы почитал литературу хоть немного, нафига сразу в форум переть с такими вопросами.
Ответы нв вопросы: что такое диструктор? что такое виртуальная функция? и подобные ты найдешь практически в любой книге по С++.
Еще раз повторю: используй массив указателей, это проще всего.Просто напомнило мне рассказ моего друга как он сдавал программирование на паскале в универе.
Тема была указатели, когда он сдавал прогу , препод(женщина) спросила указывая на какую-то переменную, что это такое. Он ответил, что это массив указателей.
После этого ответа она была в замешательстве секунд 30, и потом сразу поставила ему 5.
Видимо ей самой тяжело далось понятие указателя, а их массив просто повер ее в шок.
И все-таки действительно ли так необходимо динамическое меню. Ведь пункт меню должен создаваться (дополняться ) один раз и, соответственно ВСЕ динамическое меню должно быть delete перед завершением программы . Способ активно/неактивно отображаемо/неотображаемо неприемлем?
Поручик Голицын
шатун сибирский обыкновенный
Помню как-то я сдавал программирование в Универе, так я зафигачил двусвязный список матриц на Паскале....
Препод тоже была женщина. И тоже поставила 5, хотя теорию я ей завалил на откровенную пару

Препод тоже была женщина. И тоже поставила 5, хотя теорию я ей завалил на откровенную пару

И все-таки действительно ли так необходимо динамическое меню. Ведь пункт меню должен создаваться (дополняться ) один раз и, соответственно ВСЕ динамическое меню должно быть delete перед завершением программы . Способ активно/неактивно отображаемо/неотображаемо неприемлем?Неа. Просто много пунктов меню, и в таком случае уж слишком много памяти используется.
Блин, ты бы почитал литературу хоть немного, нафига сразу в форум переть с такими вопросами.Я вполне знаком с упомянутыми понятиями, просто они не в достаточной мере мной "прощупаны" на практике до уровня решения вот, например, такой задачи, какая приведена здесь.
Ответы нв вопросы: что такое диструктор? что такое виртуальная функция? и подобные ты найдешь практически в любой книге по С++.
Несовершенность своих знаний мне очевидна не меньше Вашего, и пришел я не за готовым кодом, а за советом.
Не все рождаются гуру, опыт приходит со временем.
Удаляюсь на очередное чтение литературы, без этого действительно никуда.
Egor_M
experienced
Я вполне знаком с упомянутыми понятиями, просто они не в достаточной мере мной "прощупаны" на практике до уровня решения вот, например, такой задачи, какая приведена здесь.Зря ты пропустил главы о динамическом выделении памяти. А если и пропустил, при решении ЛЮБОЙ задачи правильный подход сначала почитать про это в книгах, почитать документацию, потом уже лезть в форумы с вопросами, если что-то из прочитаного не понятно или ты поискав не нашел ответа на свой вопрос...
Вот из MSDN:
When new is used to allocate memory for a C++ class object, the object's constructor is called after the memory is allocated.
Use the delete operator to deallocate the memory allocated with the new operator.
>Диструктор - функция такая, которая вызывается
>при уничтожении объекта.
Никаких "диструкторов" у трупа страуса нет ;-))
>при уничтожении объекта.
Никаких "диструкторов" у трупа страуса нет ;-))
Разве не видите, что с этим примером что-то не так. Проблема возникла от того, что в нормальном коде такого быть не должно.
Egor_M
experienced
Никаких "диструкторов" у трупа страуса нет ;-))Хорошо, по русскому мне 2:)
Но "деструкторов" там дофига....