Наследование
2869
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, зачем нужны виртуальные диструкторы и т.д.
Сейчас читают
Девоньки, а вот кому женишка хорошего?
10851
127
Топ книга - толжна умереть!!!!
72563
281
Сладкий поцелуй
29220
139
Объекты будут каждый раз создаваться заново, а значение 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:)
Но "деструкторов" там дофига....