Создание пунктов меню
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;
Что я делаю неправильно???
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();
}
//------------------------------------------------
Кстати ты уверен что хочешь занимать/освобождать память по каждому появлению/скрытию формы?
Вообще когда нужно очищать память если я динамически создаю объекты?
Странно. Можно увидеть целиком текст обоих обработчиков?
Не обязательно удалять сам объект Acer?
Acer НЕ является объектом. Он всего лишь указатель на объект, точнее сказать:
Переменная Acer является указателем на данные типа TMenuItem.
TMenuItem *Acer;
Acer=new TMenuItem(this); // Данный оператор приводит к тому, что выделяется область памяти размера sizeof(TMenuItem), а переменная Acer принимает значение адреса начала выделенной области памяти
Вообще когда нужно очищать память если я динамически создаю объекты?
В данном случае есть простое правило: "Выделять и освобождать память следует на одном и том же уровне вложенности." Пример:
void func()
{
int* i = new int; // Выделение памяти
{
... /*Работа с выделенной памятью*/
}
delete i; // особождение памяти
}
В данном случае освобождать память вне внутреннего блока, т.к. выделялась она также вне его.
В принципе связка выделение в OnShow и освобождение в OnHide также соответсвует этому правилу.
//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.
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() очищает память? Не надо после нее както извращатся с удалением объектов, я уже так блин запутался с этой очисткой памяти
Вот такая шняга 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. :)
если обьект создается динамически и в конструкторе вы передаете что-то вроде this (то есть в конструктор передается владелец обьекта)
и если обьект нужен до самого когца работы с программой - то его можно вообще не удалять вручную, это сделает тот самый this, который вы передали обьекту, при собственном уничтожении
По поводу очистки памяти:
если обьект создается динамически и в конструкторе вы передаете что-то вроде this (то есть в конструктор передается владелец обьекта)
и если обьект нужен до самого когца работы с программой - то его можно вообще не удалять вручную, это сделает тот самый this, который вы передали обьекту, при собственном уничтожении
Похоже на правду. Только смущает словосочетание: "что-то вроде this". По-моему в конструктор следует передавать именно this или указатель на еще какой-нибудь компонент.
По поводу очистки памяти:
если обьект создается динамически и в конструкторе вы передаете что-то вроде this (то есть в конструктор передается владелец обьекта)
и если обьект нужен до самого когца работы с программой - то его можно вообще не удалять вручную, это сделает тот самый this, который вы передали обьекту, при собственном уничтожении
Что за бред ?!!!!
В данном случае есть простое правило: "Выделять и освобождать память следует на одном и том же уровне вложенности." Пример:
void func()
{
int* i = new int; // Выделение памяти
{
... /*Работа с выделенной памятью*/
}
delete i; // особождение памяти
}
В данном случае освобождать память вне внутреннего блока, т.к. выделялась она также вне его.
Еще больший бред !!!!
Товарищи, почитайте про язык С++, например, Страуструпа.
Что за бред ?!!!!
Товарищи, почитайте про язык С++, например, Страуструпа.
Нельзя ли уточнить в чем собственно бред?
Просьба так же указать название книги Страуструпа, издание и номер страницы на которой приведены аргументы в пользу Вашего высказывания.
Нельзя ли уточнить в чем собственно бред?
Просьба так же указать название книги Страуструпа, издание и номер страницы на которой приведены аргументы в пользу Вашего высказывания.
"Язык программирования С++", специальное издание, Б.Страуструп, п.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 при собственном удалении.
Нельзя ли уточнить в чем собственно бред?
Просьба так же указать название книги Страуструпа, издание и номер страницы на которой приведены аргументы в пользу Вашего высказывания.
"Язык программирования С++", специальное издание, Б.Страуструп, п.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 при собственном удалении.
"Язык программирования С++", специальное издание, Б.Страуструп, п.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. Имелся ввиду т.н. "хороший стиль программирования", а не правила языка. Прочитано было в некой книге название коей вспомнить не удалось. Впрочем при наличии определенной заинтересованности обещаю также найти точные координаты сказанного.