Наследование в C++

Одной из основных особенностей ООП является возможность наследования. Наследование — это способ повторного использования программного обеспечения, при котором новые производные классы (наследники) создаются на базе уже существующих базовых классов (родителей).

При создании новый класс является наследников членов и методов ранее определенного базового класса. Создаваемый путем наследования класс является производным (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;
}
Рейтинг
( Пока оценок нет )
Загрузка ...