- •2. Перегрузка функций.
- •4. Использование операторов new и delete.
- •5. Понятие классов и экземпляров классов.
- •6. Описание классов(class, struct).
- •7. Вложенные классы.
- •8. Определение объектов при помощи классов.
- •9. Конструкторы и деструкторы классов.
- •10. Атрибуты доступа к компонентам классов.
- •12. Вызов членов класса.
- •13. Перегрузка конструкторов.
- •11. Объявление и определение методов класса.
- •14. Перегрузка операторов отношения.
- •15. Перегрузка логических операторов.
- •16. Перегрузка унарных операторов.
- •17. Перегрузка бинарных операторов.
- •18. Функция оператор как член класса.
- •19. Доступ к компонентам классов в зависимости от атрибутов доступа.
- •20. Введение в наследование. Базовые классы.
- •21. Производные классы.
- •22. Ограничение доступа к элементам класса.
- •23. Конструкторы базовых и производных классов.
- •24. Виртуальные базовые классы. Чисто виртуальные функции.
- •25. Использование указателей на базовые классы и производные классы. Виртуальные методы.
- •26. Потоки ввода-вывода. Понятие потока.
- •27. Иерархия классов ввода-вывода. Основные уровни иерархии. Классы потоков.
- •28. Стандартные классы, объекты и механизмы консольного ввода/вывода.
- •29. Стандартные классы, объекты и механизмы файлового ввода/вывода.
- •30. Файлы последовательного доступа и произвольного доступа.
- •31. Основы обработки исключений в с#. Генерация исключений.
- •32. Файлы последовательного доступа и произвольного доступа.
- •34. Основы обработки исключений в с#. Генерация исключений.
23. Конструкторы базовых и производных классов.
В иерархии классов допускается, чтобы у базовых и производных классов были свои собственные конструкторы. В связи с этим возникает следующий резонный вопрос: какой конструктор отвечает за построение объекта производного класса: конструктор базового класса, конструктор производного класса или же оба? На этот вопрос можно ответить так: конструктор базового класса конструирует базовую часть объекта, а конструктор производного класса — производную часть этого объекта. И в этом есть своя логика, поскольку базовому классу неизвестны и недоступны любые элементы производного класса, а значит, их конструирование должно происходить раздельно.
Если конструктор определен только в производном классе, то все происходит очень просто: конструируется объект производного класса, а базовая часть объекта автоматически конструируется его конструктором, используемым по умолчанию.
Когда конструкторы определяются как в базовом, так и в производном классе, процесс построения объекта несколько усложняется, поскольку должны выполняться конструкторы обоих классов. В данном случае приходится обращаться к ключевому слову base, которое находит двоякое применение: во-первых, для вызова конструктора базового класса; и во-вторых, для доступа к члену базового класса, скрывающегося за членом производного класса.
С помощью формы расширенного объявления конструктора производного класса и ключевого слова base в производном классе может быть вызван конструктор, определенный в его базовом классе. Ниже приведена общая форма этого расширенного объявления:
конструктор_производного_класса(список_параметров) : base (список_аргументов) {// тело конструктора}
где список_аргументов обозначает любые аргументы, необходимые конструктору в базовом классе. Обратите внимание на местоположение двоеточия.
24. Виртуальные базовые классы. Чисто виртуальные функции.
Полиморфизм предоставляет подклассу способ определения собственной версии метода, определенного в его базовом классе, с использованием процесса, который называется переопределением метода (method overriding). Чтобы пересмотреть текущий дизайн, нужно понять значение ключевых слов virtual и override.
Виртуальным называется такой метод, который объявляется как virtual в базовом классе. Виртуальный метод отличается тем, что он может быть переопределен в одном или нескольких производных классах. Следовательно, у каждого производного класса может быть свой вариант виртуального метода. Кроме того, виртуальные методы интересны тем, что именно происходит при их вызове по ссылке на базовый класс. В этом случае средствами языка C# определяется именно тот вариант виртуального метода, который следует вызывать, исходя из типа объекта, к которому происходит обращение по ссылке, причем это делается во время выполнения. Поэтому при ссылке на разные типы объектов выполняются разные варианты виртуального метода. Иными словами, вариант выполняемого виртуального метода выбирается по типу объекта, а не по типу ссылки на этот объект.
Так, если базовый класс содержит виртуальный метод и от него получены производные классы, то при обращении к разным типам объектов по ссылке на базовый класс выполняются разные варианты этого виртуального метода.
Метод объявляется как виртуальный в базовом классе с помощью ключевого слова virtual, указываемого перед его именем. Когда же виртуальный метод переопределяется в производном классе, то для этого используется модификатор override. А сам процесс повторного определения виртуального метода в производном классе называется переопределением метода. При переопределении имя, возвращаемый тип и сигнатура переопределяющего метода должны быть точно такими же, как и у того виртуального метода, который переопределяется. Кроме того, виртуальный метод не может быть объявлен как static или abstract.
Переопределение метода служит основанием для воплощения одного из самых эффективных в C# принципов: динамической диспетчеризации методов, которая представляет собой механизм разрешения вызова во время выполнения, а не компиляции. Значение динамической диспетчеризации методов состоит в том, что именно благодаря ей в C# реализуется динамический полиморфизм.
Если при наличии многоуровневой иерархии виртуальный метод не переопределяется в производном классе, то выполняется ближайший его вариант, обнаруживаемый вверх по иерархии.
И еще одно замечание: свойства также подлежат модификации ключевым словом virtual и переопределению ключевым словом override. Это же относится и к индексаторам.
Чисто виртуальные функции. Переопределяемый метод в производном классе объявляется при помощи модификатора virtual. В производном классе для объявления переопределенного метода используется модификатор override.
Модификатор override обозначает метод или свойство производного класса, который заменяет его тем же именем и подписью в базовом классе. Базовый метод, который будет перезаписан, должен быть объявлен как virtual, abstract или override: таким способом нельзя переопределить статический метод или метод, не являющийся виртуальным. Как переопределенный, так и переопределяемый метод или свойство должны иметь одинаковые модификаторы уровня доступа.
