|
Модераторы: Snowy, MetalFan, bems, Poseidon |
|
PsiMagistr |
|
||||||||
Опытный Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Ребята, наверняка я вам уже надоел со своими вопросами, простите меня, но больше мне не к кому обратиться. Visual Basic с его недо реализацией классов так же похож на ООП Delphi как торпеда на форель. ))) А пока немножко кода:
Вот код, который Дельфи создает в самом начале, при запуске проекта. Мы видим добавление заголовочных модулей, создание класса TForm1 и создание переменной-указателя Form1. А кто нибудь видит инициализацию формы? К примеру вызов конструктора Create? Не видите? И не увидите. А между тем он написан. Но код его не здесь. Но достаточно выбрать в меню Дельфи команду: Project/View/Source и вы отыщите в открывшимся окне знакомую строку:
Многое сразу прояснилось. Однако не все. Идем дальше. Закройте наш участок кода, где описан конструктор и добавьте в проект новую форму: File/New/Form. Перейдите в код первой (главной) формы и после слова implementation напишите: uses Unit2; Мы сразу подключили модуль второй формы в код главной, чтобы удобно было работать. Запустите проект на выполнение. Что мы видим? А ничего особенного. Плавает по экрану главная форма и вот собственно и все. Однако еще не все свершились чудеса! Дело в том, что сейчас, при запуске, создались сразу ДВЕ ФОРМЫ! Наша главная и новодобавленная. Просто она то как раз и невидима. По умолчанию. Хотите убедиться? Закройте окно программы и вернитесь в Дельфи. Найдите вторую форму (Form2) и сделайте ее свойство Visible равным True. Запускайте программу. Теперь у нас две формы и мы их отлично видим. Хорошо ли это, что все добавочные формы рождаются автоматически, сразу при старте программы, (напоминаю: все конструкторы форм можно увидеть, если пройтись по меню Project/View/Source)? Ну в принципе, если у вас в проекте 2-3 формы, включая главную, то ничего страшного нет. Рождаются две-три невидимые добавочные формочки, ждут своего часа (метода show или свойства visible:=true). А вот если у нас в проекте 50-100 форм и все так и норовят запрыгнуть при старте в оперативную память?! Нда... Несладко. Особенно если все эти формы нам не нужны одновременно. Как же сделать так, чтобы побочные формы не инициализировались автоматически? На самом деле это просто. Закройте программу, вернитесь в среду Дельфи. Выберите команду меню: Project/Options и в появившемся служебном окне среды Дельфи отыщите вкладку Forms. Там вы увидите два списка. В одном из них (левом) находятся имена обеих наших форм. Правый пустой. Все формы, находящееся в правом списке инициализируются автоматически. Выделите в левом списке нашу Form2, и нажмите кнопочку с угловой скобочкой вправо. Теперь Form2 оказалась в правом списке. И это значит, что никакого ее автосоздания не будет. Закройте служебное окошко кнопочкой ОК. Запустите программу на выполнение. По экрану плавает окно главной формы. А где вторая? А ее нет. Нет, она не невидима, ее свойство Visible := True, мы сами сделали его таким еще в начале. но... Ее просто нет. Она еще не появилась на свет. Сейчас мы попробуем вызвать ее конструктор ручками. Закройте окошко программы и вернитесь в Дельфи. Отыщите главную форму, добавьте на нее кнопочку, измените ее свойство Caption на 'Рождение формы' Запишите в обработчике Onclick
Form2 - это просто указатель на будущую форму. Сама она объявлена в модуле второй формы, но модуль главной ее отлично видит, в самом начале мы сделали все подключения. В конструктор передается параметр Owner, указывая на владельца порождаемой формы. В данном случае владелец - Form1. Так что можно писать и просто Owner. В принципе все уже готово. Нам осталась одна маленькая деталь. Если вы думали, что при закрытии дочерней формы она пропадает из памяти, вы сильно ошибались. По умолчанию никакого разрушения объекта не происходит, форма остается в памяти. Невидимым балластом. Нам это не надо. Найдите дочернюю форму и в событии OnClose запишите:
Если никакого кода не писать, то параметр Action по умолчанию равен caHide, наша форма просто прячется. Мы же изменили этот параметр на caFree и заставили убраться форму из памяти. А теперь вопрос для знатоков: Если запустить программу и начать жать на кнопку, будут рождаться все новые и новые формы. Так и должно быть. Но вот с чем я так и не разобрался. Указатель на объект-форму у нас только один и это переменная Form2. Туда передается конструктор. Получается, что Form2 всегда указывает на последнюю порожденную форму. Но ведь остальные порожденные формы тоже чувствуют себя неплохо. Их можно активизировать, закрывать. Каким образом это возможно? Ведь указатель всего один. Это сообщение отредактировал(а) PsiMagistr - 27.5.2010, 08:19 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
||||||||
|
|||||||||
Dom |
|
||||
Шустрый Профиль Группа: Участник Сообщений: 121 Регистрация: 7.8.2005 Репутация: 3 Всего: 4 |
При вызове Create для формы с указанием владельца, этому владельцу в список дочерних компонентов добавляется указатель на эту форму (через InsertComponent). И при вызове деструктора этого владельца, разрушаются автоматически все его дочерние компоненты, в т.ч. и форма.
Если владельца не указывать
Это сообщение отредактировал(а) Dom - 26.5.2010, 10:59 |
||||
|
|||||
PsiMagistr |
|
|||
Опытный Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Спасибо большое, но Не совсем понял. Получается что владелец имеет указатели от всех порожденных форм, сколько бы их не было, несмотря на то, что фактически указатель всего один - Form2. -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
Dom |
|
|||
Шустрый Профиль Группа: Участник Сообщений: 121 Регистрация: 7.8.2005 Репутация: 3 Всего: 4 |
Дополню. Утечек памяти в последнем случае не будет если закрывать все эти новые формы самостоятельно ручками. Если же закрыть главное окно приложения Form1, когда есть еще открытые экземпляры Form2, то утечки будут.
Вроде бы так... |
|||
|
||||
PsiMagistr |
|
|||
Опытный Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Спасибо большое. Я понял. Но только я не совсем об этом. Я просто говорю, что у нас всего один указатель
var Form2:TForm2 И этим одним указателем управляется множество новорожденных форм. Хотя по идее он указывает только на последнюю рожденную: Form2:=TForm2.Create(Form1.Owner); Итак единственный указатель указывает на последнюю форму. Но остальные старенькие тоже неплохо управляются (сворачиваются, закрываются реагируют на щелчки). Кто в этот момент указывает на них? -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
Dom |
|
|||
Шустрый Профиль Группа: Участник Сообщений: 121 Регистрация: 7.8.2005 Репутация: 3 Всего: 4 |
Эмм, ну почему же указатель всего один? Каждый раз при вызове TForm2.Create создается новый указатель.
|
|||
|
||||
PsiMagistr |
|
|||
Опытный Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Да? А как же он появляется? Я всегда думал что объявленный в модуле дочерней формы указатель Form2 единственный. Ведь по идее указатели такие же переменные кто то их должен объявить? Или как.
-------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
kami |
|
|||
Эксперт Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 22 Всего: 72 |
Не нужно смешивать указатель на экземпляр формы и область памяти, на которую ссылается этот указатель.
Сразу после создания формы указателю на нее можно присвоить nil (более того, можно вообще без переменной-указателя обойтись), но область памяти, выделенная при создании формы/любого другого объекта от этого никуда не денется, а именно в ней (выделенной под форму памяти) содержатся все поля формы. (реализация методов, afair, имеется в одном экземпляре, сколько бы таких форм мы ни создали). Только при уничтожении формы выделенная под нее память будет возвращена менеджеру памяти программы. |
|||
|
||||
PsiMagistr |
|
|||
Опытный Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Спасибо, ками. Итак выделенная память у нас есть. Но мы создали 10 форм. Память выделена для первой формы. И для второй и для десятой тоже. Но что то же должно указывать на эту конкретную область. К ней же надо как то обращаться. Ну один указатель у нас есть. Но вот откуда берутся остальные девять штук?
Это сообщение отредактировал(а) PsiMagistr - 26.5.2010, 11:33 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
Dom |
|
|||
Шустрый Профиль Группа: Участник Сообщений: 121 Регистрация: 7.8.2005 Репутация: 3 Всего: 4 |
Ну про детали работы с памятью не расскажу, не знаю.
Должно происходить примерно следующее. При создании объекта создается указатель на него. А выражение Form2 := TForm2.Create(Form1.Owner) всего лишь присваивает этот адрес переменной Form2. |
|||
|
||||
PsiMagistr |
|
|||
Опытный Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Именно. Вот эта то переменная- указатель указывает на адрес памяти последней созданной формы. Но остальные тоже не висят в памяти балластом. Ими управлять спокойно можно. А вот что дает возможность управления? Или при create создается какой то дополнительный указатель?
Это сообщение отредактировал(а) PsiMagistr - 26.5.2010, 11:42 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
kami |
|
||||
Эксперт Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 22 Всего: 72 |
Ниоткуда В каждое событие, каждый метод любого компонента (и формы тоже) неявно передается указатель Self (сам, я). Поэтому мы имеем возможность писать в событии формы (указатель на процедуру-обработчик события хранится в выделенной под компонент памяти, т.к. является одним из его полей), например,
В противном случае действительно нужно было бы хранить валидные указатели на все созданные компоненты самому. |
||||
|
|||||
PsiMagistr |
|
||||||||
Опытный Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Спасибо, большое, kami.
И только я подумал, что понял все-все-все, как вдруг... Часть вторая. Утечка памяти или Муки ООП Сегодня утром столкнулся с совершенно неожиданным для меня результатом. 1) Создайте проект. 2) Добавьте в проект еще две формы. Итого у нас Form1, Form2, Form3. 3) Отключите автосоздание Form2 и Form3. Свойство Visible обеих форм сделайте равным True. Автосоздаваться у нас будет только одна форма (Form1) Остальные будем создавать динамически. 4) Откройте окно кода Form1 Подключите к модулю Form1 модуль Form2 Для этого после ключевого слова implementation добавьте: uses Unit2; На форме Form1 нарисуйте кнопку. Смените ее Caption на "Создать окно". Запишите в обработчик щелчка:
Мы динамически создаем Form2 Теперь перейдите в код Form2. Добавьте после раздела implementation модуль третей формы: uses Unit3; В обработчике Close запишите:
На форму Form2 добавьте кнопку. Смените ее Caption на "Создание второй формы". Запишите в обработчик OnClick;
Добавьте в обработчик Close третьей формы:
Запустите программу. Нажмите на кнопку. Породите вторую форму. Нажмите на кнопку второй формы и от второй породите третью... Итак третья форма рождена от второй Вторая является ее владельцем. НО... Закройте вторую форму. Владелец разрушен - сработало caFree обработчика-закрытия. Вот только третья форма дочерняя осталась на экране. Ай как не хорошо. Ай плохо-плохо.... Как же так??? Ведь она должна разрушиться... Это сообщение отредактировал(а) PsiMagistr - 27.5.2010, 10:40 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
||||||||
|
|||||||||
kami |
|
||||
Эксперт Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 22 Всего: 72 |
Неправда Ваша (с) чье-то. Мы видим, что владельцем(Owner-ом) формы становится владелец текущей формы (Form1.Owner и Form2.Owner - владелец первой и второй форм). Владельцем первой формы (MainForm) является Application, соответственно владельцем второй становится тоже он. С третьей та же история. Чтобы владельцем создаваемой формы стала наша, текущая форма, при нажатии на кнопку нужно писать
Поменяйте параметр в Create и всё встанет на свои места. Это сообщение отредактировал(а) kami - 27.5.2010, 12:48 |
||||
|
|||||
PsiMagistr |
|
||||||
Опытный Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
kami, Благодарю вас сердечно. Вы мне глаза открыли.
Стало быть Self в строке
относится не к порождаемой третьей форме. Это Self текущей второй формы. Правильно ли я Вас понял? P.S. Огромное спасибо за внимание. Допустим у нас в проекте только две формы. MainForm и Form2. Есть ли разница при запуске конструктора:
и
Как я понимаю, в первом случае владельцем второй формы становится владелец MainForm (объект Application), а во втором сама MainForm Это сообщение отредактировал(а) PsiMagistr - 27.5.2010, 13:46 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
||||||
|
|||||||
Правила форума "Delphi: Для новичков" | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Delphi: Для новичков | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |