![]() |
Модераторы: Snowy, MetalFan, bems, Poseidon |
![]() ![]() ![]() |
|
CodeMonkey |
|
||||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 29 Всего: 89 |
Integer и вовсе не динамический тип. Он уйдёт вместе с объектом. Объекты грубо можно считать расширенными записями. Вы же не удаляете в записи каждое Integer поле индивидуально? Вот ежели вы GetMem-ом выделите память и сохраните в указателе-поле объекта - вот это другое дело.
В одну кучу не нужно смешивать: "наличие/отсутствие свойства" и "если свойство есть, то с чем работать: с полем или свойством". Оригинальный вопрос звучал так: Здесь нет ни слова про "необходимость" или "обходимость" свойств. Вопрос про то, можно ли обращаться к свойствам из конструктора. На этот вопрос я и отвечал. Магия компилятора. Если вы посмотрите на деструктор TObject (базовый объект, который является предком любого класса в Delphi), то увидите, что его деструктор пуст, ничего не делает вовсе. В Delphi выделение и освобождение памяти под объект занимается магия компилятора. Конструктор и деструктор являются инициализаторами и чистильщиками. При этом под объект память всегда выделяется обнулённая, а при её освобождении учитываются все автоматические типы (вроде строк, интерфейсов, вариантов и т.п.). Тут надо понимать, что за исключением полей, имеющих тип автоматических типов данных, при этом не происходит индивидуальной работы с полями. Выделение и освобождение памяти происходит одним махом, на все поля сразу. Технически, на уровне ассемблера - таки да, эту работу выполняет конструктор и деструктор. Но на уровне языка ВУ это так не выглядит. Это сообщение отредактировал(а) CodeMonkey - 12.5.2011, 19:29 -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
||||
|
|||||
northener |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1361 Регистрация: 2.9.2010 Репутация: 12 Всего: 20 |
Это стоило бы выделить жирным шрифтом. Имхо. -------------------- Но только лошади летают вдохновенно. Иначе лошади разбились бы мгновенно! |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Ребята,
Решаю продолжить свои зеленые вопросы по ООП. А то из-за плохого знания предмета, выйдет сплошная сериализация сюрреализация. Да и продираться сквозь материал надо. Материал тяжелый для (моего) понимания, а на вооружении у меня только книги. Сердечно благодарю CodeMonkey и всех остальных откликающихся. Итак: 1) Верно ли что для перекрытия родительского метода в классе-потомке используется директива override тогда и только тогда, когда Метод потомка не только имеет одинаковое имя, но и одинаковый набор параметров, передаваемых в метод? Т.е. процедура является полным близнецом. Если набор параметров различен, ничего делать не нужно? 2) overload пишется тогда, когда мы хотим использовать два разных метода с одинаковыми именами, разным набором параметров и расположенных на одном иерархическом уровне. Если на разных, то это связь предок-потомок и нужен override[B] для перекрытия родительского (сам родительский при этом объявим виртуальным). 3) В чем разница между [b]overload и reitroduce. Не могу уловить, хоть ты разбейся. ))) 4) Верно ли утверждение, что деструкторы пишутся если в работе класса каким либо образом участвуют др. объекты? Т.е. в основном, чтобы их (эти другие) гасить. Например какое-либо поле определенно объектом. Или внутри метода объявлена переменная-указатель-на-объект? Много ли вообще существует НЕ-автофинализируемых типов? Я знаю что даже динам-массивы магия компилятора освобождает. Давеча попалась на глаза книга "Искусство создания компонентов Дельфи". Некто Валерий Фаронов. Утверждение там такое (цитата): "Методы класса не должны обращаться к полям, так как в общем случае они вызываются без (!) создания объекта, а следовательно в момент вызова полей просто не существует"... Постойте, как это методы не должны обращаться к полям? Они же только и делают, что обращаются. Иначе зачем они вообще нужны, если не для работы над полями? Лично я пока только один метод знаю, который способен вне объекта вызываться - constructor. Это сообщение отредактировал(а) PsiMagistr - 13.5.2011, 09:42 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Такой вопрос еще. Создал я класс - потомок от некоего класса. У того некоторый метод. Мне от него ни холодно, ни жарко и я пишу свой с тем же именем но с др набором параметрофф.
Теперь у моего класса два метода от предка и собственный. Я так понял надо overload своему методу писать, если хочу в проге оба метода использовать? А если только один хочу, свой собственный, то не надо... Так я понимаю. -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Очень любопытно. Выходит конструктор TObject НЕвиртуален.
Это сообщение отредактировал(а) PsiMagistr - 13.5.2011, 10:38 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
CodeMonkey |
|
||||||||||||||||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 29 Всего: 89 |
Рекомендую к прочтениею: http://www.delphikingdom.ru/lyceum/seminar.asp?ID=6
Нет. Директива override используется для введения новой версии виртуального метода. И, таки да, если это происходит, прототип должен полностью совпадать. А для простого перекрытия override не нужен - просто пишем новый метод. Да. И это применимо не только к методам, но и обычным процедурам, например:
Он может, но вовсе не обязан быть виртуальным. Соответственно, override будет указываться или нет, смотря по тому, что мы в итоге решим.
overload с reitroduce не связан никак, а вот override и reitroduce - понятия близкие. override "продолжает" цепочку наследования, вводя новый вариант виртуального метода. reitroduce "прерывает" цепочку наследования, "замещает" метод, вводя новый, который никак не связан с унаследованным виртуальным. reitroduce используется очень редко и только в одном случае: у тебя в предке есть виртуальный метод, но в твоём классе и любых его наследниках этот метод не нужен. Но зато у тебя есть потребность создать новый метод, который было бы очень удобно назвать так же, как и тот унаследованный виртуальный. Вот и вводишь ты метод и пишешь reintroduce. Иногда использование reitroduce говорит о допущенных ошибках при проектировании иерархии. Деструктор нужен когда ему есть что делать. Удалить поле объекта. Раз-регистрировать элемент из его контейнера при удалении. Закрыть открытый объектом файл. И т.п. В остальных случаях деструктор не нужен. К автофинализируемым типам в Delphi очевидным образом относятся все статические (просто потому, что они не нуждаются в финализации): Integer, записи и т.п., а кроме них: строки (String, AnsiString, UnicodeString, WideString), интерфейсы (IInterface, IDispatch, да и вообще любые), динамические массивы, варианты (Variant и OleVariant). Вроде, никого не забыл. Все прочие типы к таковым не относятся. К примеру, объекты, динамически выделенная память (GetMem, AllocMem, New). Но даже если память освобождается - автоматом это не значит, что делать нечего. К примеру, твой Integer может быть описателем открытого через CreateFile файла - и тогда в деструкторе файл надо закрыть. Вы путаете методы объекта и методы класса. Методы объекта - это:
Методы класса - это:
Не обязательно. Если ты хочешь сделать два метода доступными - то надо оба их объявить с overload. Если унаследованный объявлен без overload - надо в своём классе его продублировать с overload и вызвать унаследованный. Ну а в своём варианте делать что хочешь. Да.
По той простой причине, что вызываешь ты его через свой класс: [B]MyClass.Create.
Если ты вызываешь деструктор напрямую - то он может быть не виртуальным. И иногда (очень редко) так делают для хитрых целей. Но ты вызываешь деструктор через метод-обёртку Free, которая реализована у TObject. Т.е. если деструктор не виртуальный, то единственный деструктор, который сможет вызвать Free при любом раскладе будет деструктор TObject. В этом и смысл виртуальности: что при вызове из базового класса, используется метод потомка. Это сообщение отредактировал(а) CodeMonkey - 13.5.2011, 13:37 -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
||||||||||||||||
|
|||||||||||||||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
CodeMonkey, Верно ли я понимаю, что деструктор оверрайдится практически всегда. Ведь Free, как правило принадлежит предку, а он должен вызывать новую версию деструктора.
-------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
CodeMonkey |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 29 Всего: 89 |
Да, всегда.
-------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Странное дело. Просто пытаюсь разобраться. Не лупите сильно, ладно?
![]() Создаю объект А. Владелец этого объекта (Owner) - форма. Объект класса TComponent Создаю объект Б. класс TComponent. Внимание - Владелец - объект А. Заполняю свойства объекта А. Заполняю свойства объекта Б. Открываю файл, записываю данные объекта А (WriteComponent) При записи объект А должен потянуть за собой и детище - объект Б. Тянет же за собою форма все остальные компоненты. Т.е. файл должен содержать и данные А, и данные Б. Не тут то было... При записи в файл вижу данные только объекта А. Это сообщение отредактировал(а) PsiMagistr - 16.5.2011, 12:34 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
CodeMonkey |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 29 Всего: 89 |
Как я уже говорил: навскидку с TComponent я не отвечу. Надо время, чтобы смотреть и разбираться. А его у меня нет.
-------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Понятно. Ничего страшного. Спасибо. Я пока сижу, с TPresistent
-------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Вот в чем оказывается дело:
Об ответственности за сериализацию Не пугайтесь названия этого раздела. Речь пойдёт всего лишь о том, как сделать так, чтобы компонент записывал вместе с собой в поток другие. Было бы ошибкой предполагать, что компонент сериализует то, чем он владеет. Владение и ответственность за сериализацию – это разные отношения, и по умолчанию компонент не сериализует вместе с собой ничего. Впрочем, в VCL есть два класса-наследника TComponent, которые сериализуют именно то, чем владеют: это TForm и TDataModule, и если посмотреть их исходный код, можно увидеть, что в них переопределён protected-метод TComponent.GetChildren. procedure GetChildren(Proc: TGetChildProc; Root: TComponent); dynamic; где type TGetChildProc = procedure (Child: TComponent) of object; GetChildren – переопределяемый метод, в классе TComponent он пуст. Он автоматически вызывается в тот момент, когда система сериализации хочет опросить компонент о том, какие ещё компоненты нужно сохранять. В свою очередь, те компоненты тоже будут опрошены, и т. д. В аргумент Root передаётся ссылка на компонент, для которого когда-то был запущен метод TStream.WriteComponent, и если мы пришли к сериализации данного компонента через один или несколько «каскадов», Root<>Self. В GetChildren от программиста требуется, чтобы он один или несколько раз вызвал Proc, указывая в качестве аргумента те компоненты, которые нужно сериализовать вместе с данным. Например, в классах TForm и TDataModule в GetChildren организуется цикл по элементам массива TComponent.Components: var I: Integer; OwnedComponent: TComponent; begin inherited GetChildren(Proc, Root); if Root = Self then for I := 0 to ComponentCount - 1 do begin OwnedComponent := Components[I]; if not OwnedComponent.HasParent then Proc(OwnedComponent); end; end; В методе же TCustomActionList.GetChildren имеется цикл по Action’ам, которые входят в данный ActionList. Как выглядит результат работы GetChildren в dfm-формате, мы уже видели: объект сохраняется как бы «внутри» того, который отвечает за его сериализацию. Так, на представленном выше фрагменте dfm-файла, Form1 отвечает за сериализацию Button1, Button2 и ActionList1, а ActionList1 – за сериализацию Action1 и Action2. Во время же загрузки из потока компонент может узнать о том, кто отвечал за его сериализацию, и предпринять соответствующие действия. Для этого надо переопределить метод procedure SetParentComponent(Value: TComponent); dynamic; Например, TAction таким образом при десериализации может зарегистрировать себя в сериализовавшем его ActionList’е. Сериализацию наладил, содрав код в котором смыслю мало что... Дело за десериализацией. -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Delphi: Для новичков" | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Delphi: Для новичков | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |