- •45. Вызовы конструкторов в процессе работы программы.
- •48. Деструкторы.
- •49. Поля данных. Нестатические и статические поля – особенности их создания и инициализации. Правила обращения к полям. Константные поля.
- •50. Методы. Основные правила работы с методами. Константные методы. Статические методы.
- •51. Указатель this.
- •52. Дружественные функции и классы.
- •53. Перегрузка операций – общие положения.
- •54. Перегрузка операции присваивания. Особенности работы с ресурсоемкими объектами.
- •55. Перегрузка унарных операций.
- •56. Перегрузка бинарных операций.
- •57. Особенности определения классов с ключами struct и union.
- •58. Включение классов.
- •59. Наследование классов – общие положения.
- •Класс а
- •61. Общие особенности механизма простого наследования классов.
- •62. Множественное наследование.
- •63. Перечень специальных методов класса. Особенности определения конструкторов и деструкторов в производных классах.
- •64. Особенности определения и применения функций-операций «присваивание» в производных классах.
- •65. Особенности перегрузки операций в производных классах.
- •66. Общая характеристика виртуальных функций.
61. Общие особенности механизма простого наследования классов.
Дано обобщение и дополнение материалов предыдущего вопроса:
базовый класс не имеет доступ к элементам производного класса
производный класс может обращаться ко всем элементам базового класса, которые по правилам наследования (табл. 4.1) считается допустимым, кроме того объекты производного класса могут непосредственно обращаться к тем элементам базового класса, которые унаследованы с public
если какой-то элемент базового класса имеет спецификатор public, но в определении в качестве базового принят protected или private, то в производном указанный элемент будет иметь доступ protected или private соответственно, следовательно, объекты производного класса не смогут непосредственно не в метода класса обращаться к этим элементам. Для того чтобы их сделать доступными для производного класса необходимо в public производного класса указать, что имя такого элемента относится к пространству имен базового класса. Например, в определении производного класса может появится такая фраза: public: usning point:: x;
если в производном классе имя какого-то элемента базового класса используется в других целях, то этот базовый класс можно сделать доступным в производном классе с помощью операции указания области видимости print point:: print ( );
как следует из табл. 4.1, если элемент базового класса специф. как private, то независимо от спецификатора базового класса в определении производного класса этот элемент будет не доступен в производном классе. В результате создаться ситуация когда объект производного класса наследует какое-то поле и оно будет реально занимать место в поле, но добраться до него нельзя. Такое положение соответствует логике выстраивания иерархии класса, то есть иногда логичнее некоторые поля элементов работающих в базовом классе делать полностью закрытыми в потомках.
Рассмотрим когда это не подходит разработчику, покажем, как обеспечить возможность добраться до ax класса ellipse.
Определим в point следующие открытые или защищенные методы:
double geta x P ( );
{return ax; }
void set ax P (double ax P)
double getax E ( );
{return point:: getax P ( ); }
void set ax E (double ax E)
{set ax P (ax E); }
В результате мы можем менять ax значения поля ax и читать его
El2.set ax E (77.77);
cout << El2.getax E ( ) << endl;
Отдельно рассмотрим случай, когда отдельный класс наследует функцию, при этом от особого определения производного класса возможны различные ситуации.
Пусть в производном классе А не используется в дружественных функциях, тогда в производном классе и вне его унаследованное F может использоваться в точном соответствии со спецификатором доступа, который он имеет по правилу наследования, без дополнительных ограничений. Добавим в определение point и назовем его move Р, сдвигая точку из предыдущего положения в новое за время dt в соответствии с заданной точкой и ускорением. Таким образом этот метод должен изменить ax, ay и vx.
void move P (double dt)
{x += vx*dt+ax*dt*dt/2;
y += vy*dt+ay*dt*dt/2;
vx += ax*dt;
vy += at*dt; }
Так как в классе ellipse нет элементов имеющих имя move P, то мы можем использовать метод move P для передвижения элемента
El2.move P (1);
Пусть в производном классе определения имеют ту же спецификацию, что и метод F в базовом классе, тогда при непосредственном обращении от имени производного класса компилятор будет иметь в виду метод производного класса. Иногда говорят о переопределении базового метода в производном классе. В рассмотренном выше примере такая ситуация иллюстрирует print при этом до базового можно добраться если использовать операцию доступа к области видимости
Пусть в производном классе определена одномерная функция F, но имющаю другую спецификацию параметров по сравнению с F в базовом классе. Тогда при непосредственном обращении к F копия будет выбирать либо функцию базового класса, либо функцию производного класса, в соответствии с контекстом обращения, то есть в данном случае мы имеем дело с перегрузкой.
Если при определении производного класса, базовый имеет спецификатор public, то говорят от открытом наследовании, если protected, то о защищенном наследовании, если private, то о закрытом наследовании