Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.22.77.149] |
|
Страницы: (495) « Первая ... 487 488 [489] 490 491 ... 494 495 ( Перейти к последнему сообщению ) |
Сообщ.
#7321
,
|
|
|
Не обязательно знать, но вот ожидать - действительно надо. И действовать соответствующим образом |
Сообщ.
#7322
,
|
|
|
Цитата --Ins-- @ Не обязательно знать, но вот ожидать - действительно надо |
Сообщ.
#7323
,
|
|
|
Цитата --Ins-- @ Не обязательно знать, но вот ожидать - действительно надо. И действовать соответствующим образом И этот образ - это лишний код в стиле "кабы чего не вышло", да? |
Сообщ.
#7324
,
|
|
|
надо зачем? procedure Base.Clear; // виртуальный begin // очистка Base end; destructor Base.Destroy; // виртуальный begin Clear; // удаление полей Base end; procedure Child.Clear; begin inherited; // очистка Child end; destructor Child.Destroy; begin inherited; // удаляем поля Child end; т.е. в данном случае предок и может и обращается к полям потомка но зачем это может понадобится предку? (child.destroy->base.destroy->child.clear->base.clear->[?]) для этого примера: простота а для child и далее, удобство(в clear только очистка, в destroy только удаление) clear и destroy часть публичного интерфейса а как это будет в С++? я так понимаю clear будут у каждого свои(приватные) и + ещё один общий(публичный)? а в деструкторах надо заботится и об очистке и об удалении своего? |
Сообщ.
#7325
,
|
|
|
Цитата Shaggy @ а в деструкторах надо заботится и об очистке и об удалении своего? Да в плюсах, IMHO, вообще деструктор в таком случае не потребуется... |
Сообщ.
#7326
,
|
|
|
Цитата MyNameIsIgor @ Да в плюсах, IMHO, вообще деструктор в таком случае не потребуется... Да. Цитата Shaggy @ надо зачем? М-да.. Вы меня таки не понимаете. Неужели предок не может обратиться к членам-данных (не к методам) которые он унаследовал от родителя? Может конечно. Тем более никто ж не запрещает это обращение делать в деструкторе ведь правда? (ну например что-бы залогировать состояние какого-то унаследованого поля, а базовый клас этого логирования не делает). Как ж быть тогда если, как вы предалагали, раскрутить цепочку родительских деструкторов ДО своего деструктора? |
Сообщ.
#7327
,
|
|
|
Цитата Shaggy @ а как это будет в С++? Можно несколько раскрыть "это"? |
Сообщ.
#7328
,
|
|
|
Цитата Chow @ (ну например что-бы залогировать состояние какого-то унаследованого поля, а базовый клас этого логирования не делает). Как ж быть тогда если, как вы предалагали, раскрутить цепочку родительских деструкторов ДО своего деструктора? destructor XXX.Destroy; begin // запись в лог inherited; // удаление своего end; |
Сообщ.
#7329
,
|
|
|
Shaggy, т.е. мне каждый раз при написании деструктора любого класа надо напрягать моск и думать куда именно в теле деструктора следует воткнуть inherited; только ради того что-бы "кабы чего не вышло"?
Добавлено Более того? Кто за меня перевоткнет этот inherited; в другое место в случае если реализация базового класа поменяется, а я об этом и знать не буду?? |
Сообщ.
#7330
,
|
|
|
Shaggy
Ты выкручиваешься как уж на сковородке Хотя лучше\честнее было бы признать, что юзать в деструкторе виртуальные методы общего назначения (такие как Clear) - это мягко говоря, не гуд, а грубо говоря, за такие штучки надо бы руки отрывать (в том числе и самим борманам за их TList). Хоть бы предупредительный комментарий в заголовочник включили, если без подобных опусов никак. В данном случае, когда не хочется дублировать код виртуального Clear надежнее использовать дополнительный невиртуальный фантик, ну или костылик, если хотите procedure Base.DoClear; //НЕ виртуальный, приватный begin //очистка Base end; procedure Base.Clear; //виртуальный, публичный begin DoClear; end; destructor Base.Destroy; //виртуальный begin DoClear; //НЕ виртуальная очистка только Base // удаление полей Base end; |
Сообщ.
#7331
,
|
|
|
Цитата Chow @ Более того? Кто за меня перевоткнет этот inherited; в другое место в случае если реализация базового класа поменяется, а я об этом и знать не буду?? Chow, в твоих силах написать свой потомок так, что от реализации базового класса он зависеть не будет. Если используешь объекты в своих виртуальных методах (особенно с красноречивым названием Clear) ты в принципе можешь не торопиться с его уничтожением, даже не проверяя, как и где деструктор предка этот метод вызывает |
Сообщ.
#7332
,
|
|
|
PS: Когда я говорю о допустимости использования виртуальных методов в конструкторах для кастомизации\полиморфизма и т.п., то имею в виду специально предусмотренные для этого методы с понятным недвусмысленным названием и описанием того, что они могут\должны делать. В той же TForm.Create неявно вызываются методы Loaded всех загруженных в форму компонентов, и в справке четко оговаривается для чего они м.б. использованы и в каком порядке вызываются.
|
Сообщ.
#7333
,
|
|
|
Цитата Shaggy @ destructor XXX.Destroy; begin // запись в лог inherited; // удаление своего end; И да, в этом случае не буде произведена запись в лог _финального_ состояния члена-данных, так как после логирования вполне возможно оно еще изменится в недрах родительских конструкторов и мы эти изменения потеряем (для лога). |
Сообщ.
#7334
,
|
|
|
Цитата Chow @ Shaggy, т.е. мне каждый раз при написании деструктора любого класа надо напрягать моск и думать куда именно в теле деструктора следует воткнуть inherited; только ради того что-бы "кабы чего не вышло"? перекрыл виртуальный метод, посмотри в деструктор по моему просто... Цитата Chow @ Более того? Кто за меня перевоткнет этот inherited; в другое место в случае если реализация базового класа поменяется, а я об этом и знать не буду?? поменяется как? пример можно? Цитата leo @ Ты выкручиваешься как уж на сковородке а меня кто-то к стенке прижал? Цитата leo @ Хотя лучше\честнее было бы признать, что юзать в деструкторе виртуальные методы общего назначения (такие как Clear) - это мягко говоря, не гуд, а грубо говоря, за такие штучки надо бы руки отрывать (в том числе и самим борманам за их TList). Хоть бы предупредительный комментарий в заголовочник включили, если без подобных опусов никак. почему? всё что нужно знать это: в конструкторе: предок не может вызвать виртуальные методы до inherited Create; в деструкторе: предок не может вызывать после inherited Destroy всё Цитата leo @ В данном случае, когда не хочется дублировать код виртуального Clear надежнее использовать дополнительный невиртуальный фантик, ну или костылик, если хотите в каждом наследнике ты добавляешь один приватный метод и перекрываешь виртуальный а я перекрываю один виртуальный метод Цитата D_KEY @ Можно несколько раскрыть "это"? Цитата MyNameIsIgor @ Да в плюсах, IMHO, вообще деструктор в таком случае не потребуется... например добавляется указатель на сырые данные которые надо перед удалением занулить Добавлено Цитата Chow @ И да, в этом случае не буде произведена запись в лог _финального_ состояния члена-данных, так как после логирования вполне возможно оно еще изменится в недрах родительских конструкторов и мы эти изменения потеряем (для лога). каких конструкторов? мы в деструкторе находимся и каким образом изменится? запись в лог повлияет на состояние объекта что-ли? |
Сообщ.
#7335
,
|
|
|
Цитата Shaggy @ всё что нужно знать это: в конструкторе: предок не может вызвать виртуальные методы до inherited Create; в деструкторе: предок не может вызывать после inherited Destroy всё Вроде логично, но теперь глянь в справку и посмотри чему учат школьников на образцовых примерах с пояснениями Цитата The last action in a destructor's implementation is typically to call the inherited destructor to destroy the object's inherited fields. Так где зарыт источник косяков, в "бестолковой" справке, или в "бестолковы[" разработчиках, не читающих справки и сующих виртуальные Clear в деструктор, делая его не typically-наследуемым? Добавлено В догонку Flex Ferrum Цитата Flex Ferrum @ Низкий порог входа подразумевает, что среда (её дизайн) предполагают, что школьник при всём своём желании не налажает. ... Тебе фреймворк и язык не позволяют (ну, по крайней мере, я так наивно считаю) совершать грубые ошибки. И это, в общем то, правильно. Так ведь? Не совсем так. Всех желаний пытливо-шаловливых школьников предугадать невозможно, и как, я уже говорил, раздел "С\С++: Общие вопросы" пестрит школьными казусами ничуть не меньше, чем дельфийский. Просто мы тут ухватились за одну частную проблему и грызем ее до посинения, а если начать считать косяки и грабли, на которые могут нарваться начинающие, то еще неизвестно в чью пользу счет будет. Хотя у вас всегда найдется отмазка - ткнуть школьника носом в пункт №x.x.x.(x) вашего запу(нк)танного стандарта и послать читать "букварь" . В дельфийской справке тоже все расписано и разжевано со всеми Note и Warning, только почему-то в нашем (формошлепском ?!) сообществе не принято ее штудировать "от корки до корки", и соотв-но и школьников мало кто и редко когда тыкает носом - "мы все учились понемногу чему-нибудь, и как-нибудь.." Цитата Flex Ferrum @ Если заполнение этого свойства считается обязательным, почему дизайн среды заставляет пользователя указывать его явно в своём коде? Обязательным параметром считается только Owner, который и указывается в конструкторе. Для нас Азы, для вас "история болезни" - дизайн среды в первую очередь заточен на автоматическое создание компонентов из ресурсов, поэтому все компоненты, как видимые (имеющие Parent), так и невидимые имеют единый виртуальный конструктор с единственным параметром Owner, а все прочие свойства, в т.ч. и Parent, устанавливаются уже после создания компонента. Посему, создание кнопки в рантайме - это уже "продвинутая" технология, для использования которой нужны минимальные знания о том, чем отличаются Owner и Parent, и за что они отвечают. Все это достаточно подробно расписано в справке, поэтому most often forgotten может происходить не по причине банальной невнимательности, а скорее из-за полного непонимания того, что делаешь. PS: Хотя справедливости ради, стоит заметить, что для визуальных контролов можно было бы в конструкторе пытаться автоматом устанавливать Parent = Owner (через тот же SetParentComponent), но отцы-основатели решили этого не делать - значит, им виднее К тому же для школьника, на мой взгляд, было бы проще запомнить, что недостаточно просто создать контрол, а нужно его еще вставить в требуемый визуальный контейнер вызовом метода InsertControl() этого контейнера (= привычная практика для любых контейнеров). Ан, нет, отцы решили, что InsertControl будет у нас частным методом, а универсальным и рекомендуемым к использованию св-во Parent, хотя для новичков присвоение Parent:=... в выше приведенном коде теряется среди "сотни других" аналогичных присваиваний, и они не сразу запоминают, что Parent - это и есть самое важное и необходимое |