Одной из основных особенностей ООП является возможность наследования. Наследование — это способ повторного использования программного обеспечения, при котором новые производные классы (наследники) создаются на базе уже существующих базовых классов (родителей).
При создании новый класс является наследников членов и методов ранее определенного базового класса. Создаваемый путем наследования класс является производным (derived class), который в свою очередь может выступать в качестве базового класса (based class) для создаваемых классов. Если имена методов производного и базового классов совпадают, то методы производного класса перегружают методы базового класса.
При использовании наследования члены и методы кроме свойств public и private могут иметь свойство protected. Для одиночного класса описатели protected и private равносильны. Разница между protected и private проявляется при наследовании. Закрытые члены и методы, объявленные в базовом классе как protected, в производном могут использоваться как открытые (public). Защищенные (protected) члены и методы являются промежуточным вариантом между public и private.
При создании производного класса используется следующий синтаксис:
1
2 3 4 5 6 7 8 9 10 11 12 |
class name_derived_class:
type_inheritance base_class { //закрытые методы и члены класса … public: //открытые методы и члены класса … protected: //защищенные методы и члены класса … }; |
Здесь name_derived_class — имя создаваемого производного класса, type_inheritance — способ наследования, возможны следующие способы наследования: public, private и protected; base_class — имя базового типа. Следует различать тип доступа к элементам в базовом классе и тип наследования.
Типы наследования и типы доступа
Способ доступа | Спецификатор в базовом классе | Доступ в производном классе |
private | private protected public |
нет private private |
protected | private protected public |
нет protected protected |
public | private protected public |
нет protected public |
При порождении производного класса из базового, имеющего конструктор, конструктор базового типа нужно вызывать из конструктора производного класса. Конструкторы не наследуются, поэтому производный класс должен иметь собственные конструкторы. Если в конструкторе производного класса явный вызов конструктора базового типа отсутствует. то он вызывается автоматически без параметров. В случае нескольких уровней наследования конструкторы вызываются, начиная с верхнего уровня. В случае нескольких базовых типов их конструкторы вызываются в порядке объявления.
Если в описании класса есть ссылка на описываемый позже класс, то его нужно просто объявить с помощью оператора.
class new_class;
Это описание аналогично описанию прототипов функции.
Зачастую при наследовании появляются методы, которые в различных производных классах работают по разным алгоритмам, но имеют одинаковые выходные параметры и возвращаемое значение. Такие методы называются виртуальными и описываются с помощью служебного слова virtual.
В качестве примера приведем абстрактный базовый класс figure (фигура), на базе которого можно построить производные классы для реальных фигур (эллипс, окружность, квадрат, ромб, треугольник и т.д.).
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
#include «stdafx.h»
#include <iostream> #include <math.h> #define PI 3.14159; using namespace std; //базовый класс figure class figure { public: //n-количество сторон фигуры для окружности n=1 int n; //p-массив длин сторон фигуры, для окружности в p хранится радиус float *p; //конструктор figure(); //метод вычисления периметра фигуры float perimetr(); //метод вычисления площади фигуры virtual float square(); //метод вывода информации о фигуре: //ее название, периметр, площадь и т.д. virtual void show_parametri(); }; //конструктор класса фигуры figure::figure() { cout<<» Это абстрактный конструктор «<<endl; } //метод вычисления периметра, он будет //перегружаться только в классе _circle float figure::perimetr() { int i; float psum; for (psum=0, i=0; i<n; psum+=p[i], i++) return psum; } //метод вычисления площади, пока он абстрактный, в //каждом классе будет перегружаться реальным методом float figure::square() { cout<<» Квадратная фигура не абстрактна «<<endl; return 0; } //метод вывода информации о фигуре будет //перегружаться в каждом производном классе void figure::show_parametri() { cout<<» Абстрактная фигура «; } //производный класс _circle (окружность) основанный //на классе figure class _circle:public figure { public: //конструктор _circle(); //перегружаемые методы perimetr(), square(), show_parametri() float perimetr(); virtual float square(); virtual void show_parametri(); }; //производный класс RecTangle (прямоугольник), //основанный на классе figure class RecTangle:public figure { public: //конструктор RecTangle(); //перегружаемые методы square(), show_parametri() virtual float square(); virtual void show_parametri(); }; //главная функция void main() { setlocale(LC_ALL,«Rus»); _circle RR; RR.show_parametri(); RecTangle PP; PP.show_parametri(); system(«pause»); } //конструктор класса _circle _circle::_circle() { cout<<» Параметры окружности «<<endl; //в качестве сторон окружности выступает //единственный параметр радиус n=1; p=new float[n]; cout<<» Введите радиус «<<endl; cin>>p[0]; } //метод вычисления периметра окружности float _circle::perimetr() { return 2*PI*p[0]; } //метод вычисления площади окружности float _circle::square() { return PI*p[0]*p[0]; } //метод вывода параметров окружности void _circle::show_parametri() { //вывод сообщения о том, что это окружность cout<<» Это окружность «<<endl; //вывод радиуса окружности cout<<» Радиус = «<<p[0]<<endl; //вывод периметра окружности cout<<» Периметр = «<<perimetr()<<endl; //вывод площади окружности cout<<» Площадь = «<<square()<<endl; } //конструктор класса RecTangle RecTangle::RecTangle() { cout<<» Параметры прямоугольника «<<endl; //количество сторон = 4 n=4; p=new float[n]; //ввод длин сторон прямоугольника cout<<» Введите длину сторон «; cin>>p[0]>>p[1]; p[2]=p[0]; p[3]=p[1]; } //метод вычисления площади прямоугольника float RecTangle::square() { return p[0]*p[1]; } //метод вывода параметров прямоугольника void RecTangle::show_parametri() { //вывод сообщения о том, что это прямоугольник cout<<» Это прямоугольник «<<endl; //вывод длины сторон прямоугольника cout<<» a= «<<p[0]<<» b= «<<p[1]<<endl; //вывод периметра прямоугольника. Обратите внимание, //что в классе RecTangle вызывается метод perimetr() //базового класса (figure) cout<<» Периметр = «<<perimetr()<<endl; //вывод площади прямоугольника cout<<» Площадь = «<<square()<<endl; } |