Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Создание пунктов меню

1.9K
18 марта 2003 года
Mistake
23 / / 14.01.2003
У меня постоянная проблема с динамическим созданием компонентов. Я хотел динамически вставлять пункты в меню
TMenuItem *Acer;// создаю глобальный пункт меню

Потом функция FormShow:
Acer=new TMenuItem(this);
for (int i=0; i<Form1->ComboBox1->Items-Count;i++)
//Form1->ComboBox1 это список пунктов
{
Acer->Caption=Form1->ComboBox1->Items->Strings;
Acer->Name="ItemM"+i;
Acer->onClick=MenuClick;//Direct - видоизмененный PopupMenu
Direct->MenuItems->Add(Acer);// компилируется все нормально, а когда при выполнении программа доходит до этой строки возникает ошибка в которой говориться что то про адрес

В FormHide
Direct->MenuItems->Clear();
delete Acer;
Что я делаю неправильно???
1.9K
18 марта 2003 года
XilefNori
34 / / 28.02.2003
Во первых в операторе
TMenuItem *Acer;// создаю глобальный пункт меню
Ты создаешь не пункт меню, а всего лишь указатель на него(, если не ошибаюсь то все VCL компоненты создаются именно с помощью указателей.)

Пункт меню ты создаешь в операторе:
Acer=new TMenuItem(this);
Причем делаешь это всего лишь один раз! После чего пытаешься один и тот же пункт меню изменять и вставлять его в само меню. Если не ошибаюсь, то сообщение об ошибке вылетает у тебя при втором проходе цикла, как раз в тот момент когда ты вставляешь тот же пункт в меню.

Кстати, при выполнении обработчика FormHide, тебя ожидает тоже сообщение о ошибке, поскольку ты пытаешься осободить память уже освобожденную в
Direct->MenuItems->Clear(); // удаление все пунтков меню
/*
Из справки в С++ Builder:

void __fastcall Clear(void);
Description
Use Clear to free all the items listed in the Items property array.
*/

"Правильный вариант" выглядит так:
//------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
for (int i=0; i<Form1->ComboBox1->Items->Count;i++)
{
TMenuItem *Acer=new TMenuItem(this);
Acer->Caption=Form1->ComboBox1->Items->Strings;
Acer->Name="ItemM"+i;
Direct->Items->Add(Acer);
}
}
//------------------------------------------------

void __fastcall TForm1::FormHide(TObject *Sender)
{
Direct->Items->Clear();
}
//------------------------------------------------

Кстати ты уверен что хочешь занимать/освобождать память по каждому появлению/скрытию формы?
1.9K
19 марта 2003 года
Mistake
23 / / 14.01.2003
Я проверял ошибка вылетает по первому проходу цикла. Далее я очищаю память потому что пункты могут измениться и еще после Direct->Items->Clear(); не обязательно удалять сам объект Acer?
Вообще когда нужно очищать память если я динамически создаю объекты?
1.9K
19 марта 2003 года
XilefNori
34 / / 28.02.2003
Я проверял ошибка вылетает по первому проходу цикла. Далее я очищаю память потому что пункты могут измениться и еще после Direct->Items->Clear();

Странно. Можно увидеть целиком текст обоих обработчиков?

Не обязательно удалять сам объект Acer?

Acer НЕ является объектом. Он всего лишь указатель на объект, точнее сказать:
Переменная Acer является указателем на данные типа TMenuItem.

TMenuItem *Acer;
Acer=new TMenuItem(this); // Данный оператор приводит к тому, что выделяется область памяти размера sizeof(TMenuItem), а переменная Acer принимает значение адреса начала выделенной области памяти

Вообще когда нужно очищать память если я динамически создаю объекты?

В данном случае есть простое правило: "Выделять и освобождать память следует на одном и том же уровне вложенности." Пример:

void func()
{
int* i = new int; // Выделение памяти
{
... /*Работа с выделенной памятью*/
}
delete i; // особождение памяти
}

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

В принципе связка выделение в OnShow и освобождение в OnHide также соответсвует этому правилу.
358
19 марта 2003 года
moonmike
423 / / 18.10.2002
Цитата:
Originally posted by Mistake
//Direct - видоизмененный PopupMenu
Direct->MenuItems->Add(Acer);// компилируется все нормально, а когда при выполнении программа доходит до этой строки возникает ошибка в которой говориться что то про адрес


Если Direct это объект класса TPopupMenu то я у этого класса не нашел свойства MenuItem сдается мне надо писать следующим образом -
Direct->Items->Add(Acer);
потом пункты меню лучше конструировать с помощью
extern PACKAGE TMenuItem * __fastcall NewItem(const AnsiString ACaption, TShortCut AShortCut, bool AChecked, bool AEnabled, Classes::TNotifyEvent &AOnClick, Word hCtx, const AnsiString AName);

Description

Call NewItem to create and initialize a menu item when constructing a menu programmatically.

The ACaption parameter specifies the string that should appear for the menu item.
The AShortCut parameter specifies any associated shortcut.
The AChecked parameter indicates whether the menu item appears with a check mark.
The AEnabled parameter specifies whether the menu item is enabled or grayed.
The AOnClick parameter specifies an event handler that executes when the user clicks the menu item.
The hCtx parameter specifies the help context ID for the menu item.

The AName parameter specifies the name of the menu item, which can be used to refer to the menu item in code.

The menu item returned by NewItem can be added to a menu using the target parent’s Add method. If the entire menu is being created dynamically at runtime, the new menu item can be added to an array that is passed as a parameter to the NewMenu, NewPopupMenu, or NewSubMenu function.

Warning: The item returned by NewItem does not have an owner. You are responsible for freeing its memory when it is no longer needed. The Delete and Remove methods of TMenuItem do not free memory.

1.9K
19 марта 2003 года
Mistake
23 / / 14.01.2003
Короче у меня все было правильно, ну почти :-)
Direct->MenuItems->Add(Acer);//Direct похоже очень сильно был изменен я поставил обычный PopupMenu
и все запахало, далее при втором проходе цикла вылетила ошибка как и предполагалось я тогда
прямо в цикле поставил Acer=new TMenuItem(this);
потом была следующая проблема когда вызывался Hide() вылетала синяя ошибка винды и приходилось перезагружаться,
я так понял, что Direct->items->Clear() само очищает память, а я после этого опять очищаю память, поэтому я убрал delete Acer;
теперь все работает.
В итоге получилось так:


FormShow:
for (int i=0; i<Form1->ComboBox1->Items->Count;i++)//Form1->ComboBox1 это список пунктов
{
Acer=new TMenuItem(this);
Acer->Caption=Form1->ComboBox1->Items->Strings;
Acer->Name="ItemM"+i;
Acer->onClick=MenuClick;//Direct - теперь нормальный PopupMenu
Direct->Items->Add(Acer);

FormHide
Direct->MenuItems->Clear();

Вот такая шняга PopupMenu(для TList, TClassList и.т.д)->MenuItems->Clear() очищает память? Не надо после нее както извращатся с удалением объектов, я уже так блин запутался с этой очисткой памяти
1.9K
19 марта 2003 года
XilefNori
34 / / 28.02.2003
Цитата:
Originally posted by Mistake

Вот такая шняга PopupMenu(для TList, TClassList и.т.д)->MenuItems->Clear() очищает память? Не надо после нее както извращатся с удалением объектов, я уже так блин запутался с этой очисткой памяти



Цитата из справки Borland C++ Builder:

TList::Clear

Deletes all items from the list.

virtual void __fastcall Clear(void);

Description

Call Clear to empty the Items array and set the Count to 0. Clear also frees the memory used to store the Items array and sets the Capacity to 0.

(Конец цитаты)

Как и предыдуший оратор, я не нашел свойства MenuItems у объекта PopupMenu.

Говоря о методе Clear применительно к любому объекту то дествия вызываемые им заране неизвестны и потому требуют уточнения путем нажатия клавиши F1. :)

362
20 марта 2003 года
_kolyan
339 / / 03.12.2002
По поводу очистки памяти:
если обьект создается динамически и в конструкторе вы передаете что-то вроде this (то есть в конструктор передается владелец обьекта)
и если обьект нужен до самого когца работы с программой - то его можно вообще не удалять вручную, это сделает тот самый this, который вы передали обьекту, при собственном уничтожении
1.9K
20 марта 2003 года
XilefNori
34 / / 28.02.2003
Цитата:
Originally posted by _kolyan
По поводу очистки памяти:
если обьект создается динамически и в конструкторе вы передаете что-то вроде this (то есть в конструктор передается владелец обьекта)
и если обьект нужен до самого когца работы с программой - то его можно вообще не удалять вручную, это сделает тот самый this, который вы передали обьекту, при собственном уничтожении



Похоже на правду. Только смущает словосочетание: "что-то вроде this". По-моему в конструктор следует передавать именно this или указатель на еще какой-нибудь компонент.

3
20 марта 2003 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by _kolyan
По поводу очистки памяти:
если обьект создается динамически и в конструкторе вы передаете что-то вроде this (то есть в конструктор передается владелец обьекта)
и если обьект нужен до самого когца работы с программой - то его можно вообще не удалять вручную, это сделает тот самый this, который вы передали обьекту, при собственном уничтожении



Что за бред ?!!!!

Цитата:
Originally posted by XilefNori

В данном случае есть простое правило: "Выделять и освобождать память следует на одном и том же уровне вложенности." Пример:

void func()
{
int* i = new int; // Выделение памяти
{
... /*Работа с выделенной памятью*/
}
delete i; // особождение памяти
}

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



Еще больший бред !!!!

Товарищи, почитайте про язык С++, например, Страуструпа.

1.9K
20 марта 2003 года
XilefNori
34 / / 28.02.2003
Цитата:
Originally posted by Green


Что за бред ?!!!!

Товарищи, почитайте про язык С++, например, Страуструпа.



Нельзя ли уточнить в чем собственно бред?
Просьба так же указать название книги Страуструпа, издание и номер страницы на которой приведены аргументы в пользу Вашего высказывания.

3
20 марта 2003 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by XilefNori


Нельзя ли уточнить в чем собственно бред?
Просьба так же указать название книги Страуструпа, издание и номер страницы на которой приведены аргументы в пользу Вашего высказывания.



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

"Объект, созданный при помощи оператора new, существует до тех пор, пока он не удален при помощи оператора delete."

Ни о какой вложенности нет и речи. Докажите мне обратное, указав аналогично источник.

По поводу очистки памяти:
Пример:

class B;

class A
{
public:
B* pB;
A() {
pB = new B(this);
}
};

class B
{
public:
B(A*) {}
};

Под Ваше условие подходит:
"...обьект создается динамически и в конструкторе вы передаете что-то вроде this (то есть в конструктор передается владелец обьекта)"

Вот только владелец A не будет удалять B при собственном удалении.

3
20 марта 2003 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by XilefNori


Нельзя ли уточнить в чем собственно бред?
Просьба так же указать название книги Страуструпа, издание и номер страницы на которой приведены аргументы в пользу Вашего высказывания.



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

"Объект, созданный при помощи оператора new, существует до тех пор, пока он не удален при помощи оператора delete."

Ни о какой вложенности нет и речи. Докажите мне обратное, указав аналогично источник.

По поводу очистки памяти:
Пример:

class B;

class A
{
public:
B* pB;
A() {
pB = new B(this);
}
};

class B
{
public:
B(A*) {}
};

Под Ваше условие подходит:
"...обьект создается динамически и в конструкторе вы передаете что-то вроде this (то есть в конструктор передается владелец обьекта)"

Вот только владелец A не будет удалять B при собственном удалении.

1.9K
20 марта 2003 года
XilefNori
34 / / 28.02.2003
Цитата:
Originally posted by Green


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

"Объект, созданный при помощи оператора new, существует до тех пор, пока он не удален при помощи оператора delete."

Ни о какой вложенности нет и речи. Докажите мне обратное, указав аналогично источник.

По поводу очистки памяти:
Пример:

class B;

class A
{
public:
B* pB;
A() {
pB = new B(this);
}
};

class B
{
public:
B(A*) {}
};

Под Ваше условие подходит:
"...обьект создается динамически и в конструкторе вы передаете что-то вроде this (то есть в конструктор передается владелец обьекта)"

Вот только владелец A не будет удалять B при собственном удалении.



Совершенно согласен.

Однако, в первом посте про очистку памяти, подразумевались не все объекты, а только компоненты библиотетки VCL конструкторы которых при их(компонентов) создании принимают указатели типа:
Classes::TComponent* AOwner
И в этом случае при уничтожении владельца, потомок также автоматически уничтожается.

Было написано в книге Архангельского C++ Builder 5. Точно где не помню, но если интересно, могу поискать, когда доберусь до книги.

По поводу new/delete. Имелся ввиду т.н. "хороший стиль программирования", а не правила языка. Прочитано было в некой книге название коей вспомнить не удалось. Впрочем при наличии определенной заинтересованности обещаю также найти точные координаты сказанного.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог