Наследование классов — очень мощная возможность в объектно ориентированном программировании. Оно позволяет создавать производные классы (классы наследники), взяв за основу все методы и элементы базового класса (класса родителя). Таким образом экономится масса времени на написание и отладку кода новой программы. Объекты производного класса свободно могут использовать всё, что создано и отлажено в базовом классе. При этом, мы можем в производный класс, дописать необходимый код для усовершенствования программы: добавить новые элементы, методы и т.д.. Базовый класс останется нетронутым. Эту тему вполне возможно освоить новичкам. Необходимо только познакомиться с синтаксисом и некоторыми особенностями. Ниже приведен простой код программы, который мы детально разберем под листингом. В этой программе созданы два класса: базовый — FirstClass
и производный от него SecondClass
.
Пример:
#include <iostream> using namespace std; class FirstClass // базовый класс { protected: // спецификатор доступа к элементу value int value; public: FirstClass() { value = 0; } FirstClass( int input ) { value = input; } void show_value() { cout << value << endl; } }; class SecondClass : public FirstClass // производный класс { public: SecondClass() : FirstClass () // конструктор класса SecondClass вызывает конструктор класса FirstClass {} SecondClass(int inputS) : FirstClass (inputS) // inputS передается в конструктор с параметром класса FirstClass {} void ValueSqr () // возводит value в квадрат. Без спецификатора доступа protected эта функция не могла бы изменить значение value { value *= value; } }; int main() { setlocale(LC_ALL, "rus"); FirstClass F_object(3); // объект базового класса cout << "value F_object = "; F_object.show_value(); SecondClass S_object(4); // объект производного класса cout << "value S_object = "; S_object.show_value(); // вызов метода базового класса S_object.ValueSqr(); // возводим value в квадрат cout << "квадрат value S_object = "; S_object.show_value(); //F_object.ValueSqr(); // базовый класс не имеет доступа к методам производного класса cout << endl; return 0; }
Разбирать пример будем по-порядку. Ранее мы работали только со спецификаторами доступа private
и public
. В строке 6 мы встретили новый для нас спецификатор доступа protected
. Он отличается от private
тем, что разрешает доступ к элементам базового класса из производных классов. Если бы элемент value
находился в поле private
, то доступ к нему был бы закрыт и мы бы не могли изменить его значение через объект класса SecondClass
, используя функцию ValueSqr()
, определённую в строках 34 — 37.
Чтобы было наглядней, отличия спецификаторов доступа можно отобразить в таблице:
private | protected | public | |
Доступ из тела класса | открыт | открыт | открыт |
Доступ из производных классов | закрыт | открыт | открыт |
Доступ из внешних функций и классов | закрыт | закрыт | открыт |
Если вы создаёте класс, который в дальнейшем планируете использовать, как базовый, то объявляйте в нём поле protected
вместо private
. Иначе объекты производного класса не смогут обращаться к элементам базового.
Ниже, в строках 8 — 22, определены методы базового класса. Конструктор без параметров FirstClass()
, конструктор с параметром FirstClass( int input )
и метод void show_value()
, который выводит значение value
на экран.
Определение производного находится в строках 25 — 38. Синтаксис наследования такой — class Имя_Производного_Класса : спецификатор доступа Имя_Базового_Класса { } ; Двоеточие :
не путайте с двойным двоеточием ::
(определение области действия). Используя этот оператор мы показываем, наследником какого класса является производный класс.
Важной особенностью производного класса, является то, что хоть он и может использовать все методы и элементы полей protected
и public
базового класса, но он не может обратиться к конструктору с параметрами. Если конструкторы в производном классе не определены, при создании объекта сработает конструктор без аргументов базового класса. А если нам надо сразу при создании объекта производного класса внести данные, то для него необходимо определить свои конструкторы. В нашем примере показано, как же мы всё-таки можем использовать уже готовые конструкторы базового класса, чтобы не набирать код конструкторов снова — строки 28 — 32. Для этого при определении конструктора производного класса после его имени следует поставить оператор :
и имя конструктора базового класса, который необходимо вызвать, при создании объекта производного класса — SecondClass() : FirstClass (){}
. Тело конструктора оставляем пустым т.к. всю работу проделает конструктор базового класса. В случае конструктора с параметром, этот параметр мы передаем в конструктор с параметром базового класса SecondClass(int inputS) : FirstClass (inputS){}
— строка 31.
В main-функции создаем объекты базового и производного классов — FirstClass F_object(3);
и SecondClass S_object(4);
и отображаем их значения value
на экран. Как видите в строке 50, объект производного класса без проблем обращается к методу show_value()
базового класса. Так, будто это его собственный метод. Ниже вызываем метод, который возводит значения value
производного класса в квадрат. И выводим это изменённое значение на экран. А вот если мы захотим вызвать этот метод — F_object.ValueSqr();
— для объекта базового класса, компилятор нам этого не позволит сделать и выдаст ошибку. Это еще одна важная особенность — производный класс имеет доступ к базовому классу, а базовый класс, даже «не знает» о существовании производного и не может пользоваться его кодом.
Результат работы программы:
value F_object = 3
value S_object = 4
квадрат value S_object = 16
В виде списка приведу основную информацию о наследовании классов, которую важно знать:
- Наследование — это определение производного класса, который может обращаться ко всем элементам и методам базового класса за исключением тех, которые находятся в поле
private
; - Производный класс еще называют потомком или подклассом, а базовый — родитель или надкласс;
- Синтаксис определения производного класса: class Имя_Производного_Класса : спецификатор доступа Имя_Базового_Класса { /*код*/ } ;
- Производный класс имеет доступ ко всем элементам и методам базового класса, а базовый класс может использовать только свои собственные элементы и методы.
- В производном классе необходимо явно определять свои конструкторы, деструкторы и перегруженные операторы присваивания из-за того, что они не наследуются от базового класса. Но их можно вызвать явным образом при определении конструктора, деструктора или перегрузки оператора присваивания производного класса, например таким образом (для конструктора): Конструктор_Производного_Класса (/*параметры*/) : Конструктор_Базового_Класса ( /*параметры*/) { } .
- Еще один важный момент при наследовании — перегруженные функции-методы класса потомка. В данном примере мы его не рассматривали. Но чтобы вы знали, если в классе родителе и в его классах потомках встречаются методы с одинаковым именем, то для объектов класса потомка компилятор будет использовать методы именно класса потомка. Перегруженные методы класса потомка, могут вызывать методы класса родителя. В таком случае важно помнить, что необходимо правильно определить область действия с помощью оператора
::
.Иначе компилятор воспримет это, как вызов функцией самой себя. Наглядно, если бы мы перегрузили в классеSecondClass
функциюshow_value()
— это выглядело бы так:
void show_value() { if(value != 0) FirstClass :: show_value(); }
Эта запись указывает компилятору — если значение value
не равно нулю — вызвать метод show_value()
класса FirstClass
. А он в свою очередь, отобразит это значение на экране.
Думаю для первого знакомства с наследованием классов этого достаточно. Это бесспорно классная возможность языка С++. Она помогает экономить массу времени на написание и отладку кода с нуля. Вместо этого мы можем использовать уже готовый и отлаженный код и подстраивать его под новые задачи, которые поставлены перед нами. При этом наша новая программа будет занимать намного меньше строк, что значительно улучшит её читабельность.
Комментарии
oeveyijde
[url=http://usa-onlineprednisone.net/]usa-onlineprednisone.net.ankor[/url] salbutamol-ventolin-buy.net.ankor http://online-viagracanada.net/