Здравствуйте, s.ts, Вы писали:
ST>Здравствуйте, LaptevVV, Вы писали:
LVV>>11. Сформулируйте принцип подстановки.
ST>?
Впервые его сформулировала Барбара Лисков
Ответ из моей книжки
Открытое наследование устанавливает между классами отношение "является": класс-наследник является разновидностью класса-родителя. И это не просто словесная формулировка — она непосредственно поддерживается компилятором. Когда мы пишем, что класс Derived (производный) открыто наследует от класса Base (базовый), мы сообщаем компилятору, что каждый объект типа Derived является также объектом класса Base. С практической точки зрения это означает, что везде, где может быть использован объект типа Base, вместо него разрешается подставлять объект типа Derived — это и есть принцип подстановки.
Этот принцип работает и для ссылок, и для указателей: вместо ссылки (указателя) на базовый класс может быть подставлена ссылка (указатель) на класс-наследник. Преобразование типа при этом прописывать не обязательно — оно выполняется автоматически. Эккель называет такое приведение типов повышающим.
Обратное — неверно! Например, будильник является часами, но не всякие часы — будильник. Здесь часы — базовый класс, а будильник — производный.
LVV>>13. Объясните, что такое "срезка" или "расщепление".
ST>?
Коротко — в производном классе могут быть определены дополнительные поля. Во время присваивания при преобразовании по принципу подстановки "лишние поля в объект базового класса. естественно, не попадают.
Чтобы понять, в чем дело, обратимся к классам точек. Рассмотрим простой пример с двумерными и трехмерными точками.
Point3D b(1,2,3);
Point2D a = b; // подстановка в конструкторе копирования - срезка
a = b; // подстановка в присваивании - срезка
Работает принцип подстановки, однако нас поджидает неприятность: так как базовый класс ничего не знает о своих наследниках, то в переменную a копируется только Point2D-часть трехмерной точки. Этот эффект называется срезкой [Страуструп] или расщеплением [Брюс Эккель]; он частенько приводит к ошибкам. Например, при передаче параметра по значению, как мы знаем, работает конструктор копирования, поэтому в таких случаях тоже может произойти срезка. При передаче параметра по ссылке (или по указателю) ничего подобного не происходит.
LVV>>23. Может ли конструктор быть виртуальным? А деструктор?
ST>По поводу конструктора интересен ответ. Какова Ваша религия ?
Синтаксически это запрещено стандартом. Однако можно определить виртуальную производящую (термин Элджера) функцию. Эту функцию и можно назвать виртуальным конструктором, так как ее назначение — сконструировать объект. Идиома виртуального конструктора — основа паттерна Фабрика
LVV>>34. Приведите классификацию целей наследования.
ST>Приведите плз.
Тимоти Бадд приводит интересную классификацию форм наследования. Форма наследования определяет — для чего, с какой целью используется наследование. Бадд считает, что порождение дочернего класса может быть выполнено по следующим причинам:
специализация. Класс-наследник является специализированной формой родительского класса — в наследнике просто переопределяются методы. Принцип подстановки выполняется. Очевидно, что такая форма наследования в С++ реализуется простым открытым наследованием. Примером является наследование часы -> будильник;
спецификация. Дочерний класс реализует поведение, описанное в родительском классе. Ясно, что в С++ такая форма реализуется простым открытым наследованием от абстрактного класса;
конструирование. Класс-наследник использует методы базового класса, но не является его подтипом (принцип подстановки не выполняется). В С++ такую форму можно реализовать простым закрытым наследованием;
расширение. В класс-потомок добавляют новые методы, расширяя поведение родительского класса. Хотя Т. Бадд выделяет эту форму наследования в отдельный вид, однако, на мой взгляд, она мало отличается от специализации, особенно учитывая то, что принцип подстановки в такой форме выполняется;
обобщение. Дочерний класс обобщает поведение базового класса. Обычно такое наследование используется в тех случаях, когда мы не можем изменить поведение базового класса (например, базовый класс является библиотечным классом);
ограничение. Класс-наследник ограничивает поведение родительского класса. Очевидно, что в С++ такой вид наследования реализуется простым закрытым наследованием (пример — TUniversalDeque -> TStack );
варьирование. Базовый класс и класс-потомок являются вариациями на одну тему, однако связь "класс-подкласс" произвольна, например, "квадрат-прямоугольник" или "прямоугольник-квадрат". Этот форму наследования лучше не применять;
комбинирование. Дочерний класс наследует черты нескольких классов — это множественное наследование.
ST>Вообще некоторые вопросы смахивают не на общепризнанное знание, а на знание лекций конкретого преподавателя.
Только последний
Остальные — должен знать каждый студент. Другое дело, что порядок вопросов — да. соответствует главе "Наследование" в лекциях.