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

Наследование классов

Как видим, выбор способа доступа к компонентам базовых классов при наследовании определяется теми же соображениями, что и для компонентов обычного класса:

•открытые (public) компоненты доступны из любого места программы, т.е. они являются глобальными;

•защищенные (protected) компоненты доступны внутри класса, в котором они определены, и во всех его производных классах;

•закрытые (private) компоненты доступны только внутри того класса, в котором они определены.

Итак, при обработке сообщения объектом рассматриваемого класса используются, во-первых, общедоступные компоненты всех классов программы, во-вторых, защищенные компоненты базовых и рассматриваемого классов, в-третьих, собственные компоненты рассматриваемого класса.

Инициализация объектов, представляющих базовые и производные классы, может быть задана в их конструкторах, причем конструкторы выполняются в порядке наследования (конструктор базового класса выполняется раньше конструктора производного класса), а деструкторы – в обратном (деструктор производного класса выполняется раньше деструктора базового класса).

Ранее было сказано, что при проектировании иерархии классов для инициализации компонентных данных можно воспользоваться расширенной формой объявления конструкторов производных классов, позволяющей через список инициализации членов, в котором могут быть представлены явные вызовы конструкторов прямых базовых классов, передавать по цепочке наследования всем требуемым конструкторам косвенных базовых классов необходимые им аргументы вызова.

Здесь же отметим, что при таком способе организации списка инициализации членов допустимо использование одних и тех же аргументов вызова для базового и производного классов. Для производного класса допустимо также игнорирование всех аргументов вызова, в этом случае необходима их передача напрямую в базовый класс. Если инициализация производится только в производном классе, аргументы вызова передаются обычным образом.

Приведем пример открытого одиночного наследования компонентов базового класса Complex_based его производным классом Complex_derived, который к наследуемым компонентам добавляет собственную компонентную функцию add():

//Пример 37

//C++ Одиночное наследование

#include <iostream> using namespace std; struct Complex_based {

//Компонентные функции — все общедоступные (public)

//Конструктор объектов базового класса

Complex_based(double r = 0.0, double i = 0.0) : re(r), im(i)

{

cout << «Конструктор базового класса» << endl;

}

103

studfiles.net

Наследование в 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 — имя базового типа. Следует различать тип доступа к элементам в базовом классе и тип наследования.

Типы наследования и типы доступа

Способ доступаСпецификатор в базовом классеДоступ в производном классе
privateprivate
protected
public
нет
private
private
protectedprivate
protected
public
нет
protected
protected
publicprivate
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;
}


Похожие записи:

kvodo.ru

Типы наследования Простое наследование

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

Другими словами, класс-наследник реализует спецификацию уже существующего класса (базовый класс). Это позволяет обращаться с объектами класса-наследника точно так же, как с объектами базового класса 1

Класс, от которого произошло наследование, называется базовым или родительским (англ. base class). Классы, которые произошли от базового, называются потомками, наследниками или производными классами (англ. derived class).

В некоторых языках используются абстрактные классы. Абстрактный класс — это класс, который описан в программе, имеет поля, функции, но не используется для создания объекта. Объекты создаются только на основе производных классов, наследованных от абстрактного. Например, абстрактным классом может быть базовый класс «сотрудник ВУЗа», от которого наследуются классы «аспирант», «профессор» и т.д. Т.к. производные классы имеют общие поля и функции (например, поле «год рождения»), то эти члены класса могут быть описаны в базовом классе. В программе создаются объекты на основе классов «аспирант», «профессор», но нет смысла создавать объект на основе класса «сотрудник вуза».

Множественное наследование

При множественном наследовании у класса может быть более одного предка. В этом случае класс наследует методы всех предков. Достоинства такого подхода в большей гибкости. Множественное наследование реализовано в C++. Из других языков, предоставляющих эту возможность, можно отметить Python. Множественное наследование поддерживается в языке UML.

Множественное наследование — потенциальный источник ошибок, которые могут возникнуть из-за наличия одинаковых имен методов в предках. В языках, которые позиционируются как наследники C++ (Java, C# и др.), от множественного наследования было решено отказаться в пользу интерфейсов.

Большинство современных объектно-ориентированных языков программирования (C#, Java, Delphi и др.) поддерживает возможность одновременно наследоваться от класса-предка и реализовать методы нескольких интерфейсов одним классом. Этот механизм позволяет во многом заменить множественное наследование — методы интерфейсов необходимо переопределять явно, что исключает ошибки при наследовании функциональности одинаковых методов различных классов-предков.

Наследование в языке C++

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

class A{ //базовый класс

};

class B : public A{ //public наследование

}

class C : protected A{ //protected наследование

}

class Z : private A{ //private наследование

}

В C++ существует три типа наследования: public, protected, private. Спецификаторы доступа членов базового класса меняются в потомках следующим образом:

  • при public-наследовании все спецификаторы остаются без изменения.

  • при protected-наследовании все спецификаторы остаются без изменения, кроме спецификатора public, который меняется на спецификатор protected (то есть public-члены базового класса в потомках становятся protected).

  • при private-наследовании все спецификаторы меняются на private.

Одним из основных преимуществ public-наследования является то, что указатель на классы—наследники может быть неявно преобразован в указатель на базовый класс, то есть для примера выше, можно написать

A* a = new B;

Эта интересная особенность открывает возможность динамической идентификации типа.

2) Интерфе́йс(от лат. inter — между и лат. face — поверхность) — это семантическая и синтаксическая конструкция в коде программы, используемая для специфицирования услуг, предоставляемых классом или компонентом.

Интерфейс определяет границу взаимодействия между классами или компонентами, специфицируя определенную абстракцию, которую осуществляет реализующая сторона. В отличие от большинства других видов интерфейсов, интерфейс в ООП является строго формализованным элементом объектно-ориентированного языка и, в качестве семантической конструкции, широко используется кодом программы. К примеру, интерфейс «Cloneable» может описать абстракцию клонирования (создания точных копий) объектов, специфицировав метод «Clone». Тогда любой класс, способный создать свою копию, может задекларировать себя как Cloneable и предоставить метод Clone. Причем вызывающей стороне достаточно знать только описание интерфейса. Таким образом, интерфейсы позволяют рассоединить части программной системы в модули без взаимной зависимости кода.

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

Интерфейсы в C++

Роль интерфейсов в C++ выполняют абстрактные классы.

3) Конструктор—специальный метод класса в объектно-ориентированном программировании, служащий для инициализации объекта при его создании (например выделения памяти). В языках программирования С++ или Java конструктором класса называется функция, имеющая то же имя, что и сам класс, и не возвращающая никакого значения. Говоря более простым языком, конструктором называется тот метод класса, который вызывается автоматически при создании экземпляра класса.

Иногда используют более узкие термины: конструктор по умолчанию, конструктор копирования, конструктор преобразования.

studfiles.net

Наследование (программирование) — это… Что такое Наследование (программирование)?

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

Другими словами, класс-наследник реализует спецификацию уже существующего класса (базовый класс). Это позволяет обращаться с объектами класса-наследника точно так же, как с объектами базового класса.

Типы наследования

Простое наследование

Класс, от которого произошло наследование, называется базовым или родительским (англ. base class). Классы, которые произошли от базового, называются потомками, наследниками или производными классами (англ. derived class).

В некоторых языках используются абстрактные классы. Абстрактный класс — это класс, содержащий хотя бы один абстрактный метод, он описан в программе, имеет поля, методы и не может использоваться для непосредственного создания объекта. То есть от абстрактного класса можно только наследовать. Объекты создаются только на основе производных классов, наследованных от абстрактного. Например, абстрактным классом может быть базовый класс «сотрудник вуза», от которого наследуются классы «аспирант», «профессор» и т. д. Так как производные классы имеют общие поля и функции (например, поле «год рождения»), то эти члены класса могут быть описаны в базовом классе. В программе создаются объекты на основе классов «аспирант», «профессор», но нет смысла создавать объект на основе класса «сотрудник вуза».

Множественное наследование

При множественном наследовании у класса может быть более одного предка. В этом случае класс наследует методы всех предков. Достоинства такого подхода в большей гибкости. Множественное наследование реализовано в C++. Из других языков, предоставляющих эту возможность, можно отметить Python и Эйфель. Множественное наследование поддерживается в языке UML.

Множественное наследование — потенциальный источник ошибок, которые могут возникнуть из-за наличия одинаковых имен методов в предках. В языках, которые позиционируются как наследники C++ (Java, C# и др.), от множественного наследования было решено отказаться в пользу интерфейсов. Практически всегда можно обойтись без использования данного механизма. Однако, если такая необходимость все-таки возникла, то, для разрешения конфликтов использования наследованных методов с одинаковыми именами, возможно, например, применить операцию расширения видимости — «::» — для вызова конкретного метода конкретного родителя.

Попытка решения проблемы наличия одинаковых имен методов в предках была предпринята в языке Эйфель, в котором при описании нового класса необходимо явно указывать импортируемые члены каждого из наследуемых классов и их именование в дочернем классе.

Большинство современных объектно-ориентированных языков программирования (C#, Java, Delphi и др.) поддерживают возможность одновременно наследоваться от класса-предка и реализовать методы нескольких интерфейсов одним и тем же классом. Этот механизм позволяет во многом заменить множественное наследование — методы интерфейсов необходимо переопределять явно, что исключает ошибки при наследовании функциональности одинаковых методов различных классов-предков.

Единый базовый класс

В ряде языков программирования все классы явно или неявно наследуются от некого базового класса. Smalltalk был одним из первых языков, в которых использовалась эта концепция. К таким языкам относятся Objective-C (NSObject), Perl (UNIVERSAL), Eiffel (ANY), Java (java.lang.Object), C# (System.Object), Delphi (TObject).

Наследование в языках программирования

Visual Basic

Наследование в Visual Basic:

Class A 'базовый класс
End Class
 
Class B : Inherits A    'наследование от A
End Class
 
Noninheritable Class C     'Класс, который нельзя наследовать (final в Java)
End Class
 
MustInherit Class Z 'Класс, который обязательно наследовать (абстрактный класс)
End Class

C++

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

class A{    //базовый класс
};
 
class B : public A{    //public наследование
};
 
class C : protected A{    //protected наследование
};
 
class Z : private A{    //private наследование
};

В C++ существует три типа наследования: public, protected, private. Спецификаторы доступа членов базового класса меняются в потомках следующим образом:

ANSI ISO IEC 14882 2003

Если класс объявлен как базовый для другого класса со спецификатором доступа public, тогда public члены базового класса доступны как public члены производного класса, protected члены базового класса доступны как protected члены производного класса.

Если класс объявлен как базовый для другого класса со спецификатором доступа protected, тогда public и protected члены базового класса доступны как protected члены производного класса.

Если класс объявлен как базовый для другого класса со спецификатором доступа private, тогда public и protected члены базового класса доступны как private члены производного класса.

\ANSI ISO IEC 14882 2003

Одним из основных преимуществ public-наследования является то, что указатель на классы-наследники может быть неявно преобразован в указатель на базовый класс, то есть для примера выше можно написать:

Эта интересная особенность открывает возможность динамической идентификации типа (RTTI).

Delphi (Object Pascal)

Для использования механизма наследования в Delphi необходимо в объявлении класса справа от слова class указать класс предок:

Предок:

TAncestor = class
private
protected
public
  // Виртуальная процедура
  procedure VirtualProcedure; virtual; abstract; 
  procedure StaticProcedure;
end;

Наследник:

TDescendant = class(TAncestor)
private
protected
public
  // Перекрытие виртуальной процедуры
  procedure VirtualProcedure; override;
  procedure StaticProcedure;
end;

Абсолютно все классы в Delphi являются потомками класса TObject. Если класс-предок не указан, то подразумевается, что новый класс является прямым потомком класса TObject.

Множественное наследование в Delphi частично поддерживается за счёт использования классов-помощников (Сlass Helpers).

Python

Python поддерживает как одиночное, так и множественное наследование. При доступе к атрибуту порядок просмотра производных классов называется порядком разрешения метода (англ. method resolution order)[1].

class Ancestor1(object):   # Предок 1
    def m1(self): pass
class Ancestor2(object):   # Предок 2
    def m1(self): pass
class Descendant(Ancestor1, Ancestor2):   # Наследник
    def m2(self): pass
 
d = Descendant()           # инстанциация
print d.__class__.__mro__  # порядок разрешения метода:
(<class '__main__.Descendant'>, <class '__main__.Ancestor1'>, <class '__main__.Ancestor2'>, <type 'object'>)

С версии Python 2.2 в языке сосуществуют «классические» классы и «новые» классы. Последние являются наследниками object. «Классические» классы будут поддерживаться вплоть до версии 2.6, но удалены из языка в Python версии 3.0.

Множественное наследование применяется в Python, в частности, для введения в основной класс классов-примесей (англ. mix-in).

PHP

Для использования механизма наследования в PHP необходимо в объявлении класса после имени объявляемого класса-наследника указать слово extends и имя класса-предка:

class Descendant extends Ancestor {
}

В случае перекрытия классом-наследником свойств и методов предка, доступ к свойствам и методам предка можно получить с использованием ключевого слова parent:

class A {
  function example() {
    echo "Вызван метод A::example().<br />\n";
  }
}
 
class B extends A {
  function example() {
    echo "Вызван метод B::example().<br />\n";
    parent::example();
  }
}

Objective-C

@interface MyNumber : NSObject { 
   int num;
}
- (int) num;
- (void) setNum: (int) theNum;
@end
 
@implementation
- (id) init { 
   self = [super init];
   return self;
}
 
- (int) num {
   return num;
}
 
- (void) setNum: (int) theNum {
   num = theNum;
}
@end

Переопределенные методы не нужно объявлять в интерфейсе.

Java

Пример наследования от одного класса и двух интерфейсов:

        public class A { }
        public interface I1 { }
        public interface I2 { }
        public class B extends A implements I1, I2 { }

Директива final в объявлении класса делает наследование от него невозможным.

C#

Пример наследования от одного класса и двух интерфейсов:

        public class A { }
        public interface I1 { }
        public interface I2 { }
        public class B : A, I1, I2 { }

Наследование от типизированных классов можно осуществлять, указав фиксированный тип, либо путем переноса переменной типа в наследуемый класс:

        public class A<T>
        { }
        public class B : A<int>
        { }
        public class B2<T> : A<T>
        { }

Допустимо также наследование вложенных классов от классов, их содержащих:

    class A
    {
        public class B : A { }
    }

Директива sealed в объявлении класса делает наследование от него невозможным.[2]

Ruby

class Parent
 
  def public_method
    "Public method"
  end
 
  private
 
    def private_method
      "Private method"
    end
 
end
 
class Children < Parent
 
  def public_method
    "Redefined public method"
  end
 
  def call_private_method
    "Ancestor's private method: " + private_method
  end
 
end

Класс Parent является предком для класса Children, у которого переопределен метод public_method.

children = Children.new
children.public_method #=> "Redefined public method"
children.call_private_method #=> "Ancestor's private method: Private method"

Приватные методы предка можно вызывать из наследников.

JavaScript

var Parent = function( data ) {
    this.data = data || false;
    this.public_method = function() { return 'Public Method'; }
}
 
var Child = function() {
    this.public_method = function() { return 'Redefined public method'; }
    this.getData = function() { return 'Data: ' + this.data; }
}
 
Child.prototype = new Parent('test');
var Test = new Child();
 
Test.getData(); // => "Data: test"
Test.public_method(); // => "Redefined public method"
Test.data; // => "test"

Класс Parent является предком для класса Children, у которого переопределен метод public_method. В JavaScript используется прототипное наследование.

Конструкторы и деструкторы

В С++ конструкторы при наследовании вызываются последовательно от самого раннего предка до самого позднего потомка, а деструкторы наоборот — от самого позднего потомка до самого раннего предка.

class First
{
public:
    First()  { cout << ">>First constructor" << endl; }
    ~First() { cout << ">>First destructor" << endl; }
};
 
class Second: public First
{
public:
    Second()  { cout << ">Second constructor" << endl; }
    ~Second() { cout << ">Second destructor" << endl; }
};
 
class Third: public Second
{
public:
    Third()  { cout << "Third constructor" << endl; }
    ~Third() { cout << "Third destructor" << endl; }
};
 
// выполнение кода
Third *th = new Third();
delete th;
 
// результат вывода
/*
>>First constructor
>Second constructor
Third constructor
 
Third destructor
>Second destructor
>>First destructor
*/

См. также

Примечания

Ссылки

dic.academic.ru

6. Использование наследования при создании класса.

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

Другими словами, класс-наследник реализует спецификацию уже существующего класса (базовый класс). Это позволяет обращаться с объектами класса-наследника точно так же, как с объектами базового класса.

Простое наследование

Класс, от которого произошло наследование, называется базовым или родительским (англ. base class). Классы, которые произошли от базового, называются потомками,наследниками или производными классами (англ. derived class).

В некоторых языках используются абстрактные классыАбстрактный класс — это класс, содержащий хотя бы один абстрактный метод, он описан в программе, имеет поля,методы и не может использоваться для непосредственного создания объекта. То есть от абстрактного класса можно только наследовать. Объекты создаются только на основе производных классов, наследованных от абстрактного. Например, абстрактным классом может быть базовый класс «сотрудник вуза», от которого наследуются классы «аспирант», «профессор» и т. д. Так как производные классы имеют общие поля и функции (например, поле «год рождения»), то эти члены класса могут быть описаны в базовом классе. В программе создаются объекты на основе классов «аспирант», «профессор», но нет смысла создавать объект на основе класса «сотрудник вуза».

Множественное наследование

Основная статьяМножественное наследование

При множественном наследовании у класса может быть более одного предка. В этом случае класс наследует методы всех предков. Достоинства такого подхода в большей гибкости. Множественное наследование реализовано в C++. Из других языков, предоставляющих эту возможность, можно отметить Python и Эйфель. Множественное наследование поддерживается в языке UML.

Множественное наследование — потенциальный источник ошибок, которые могут возникнуть из-за наличия одинаковых имен методов в предках. В языках, которые позиционируются как наследники C++ (JavaC# и др.), от множественного наследования было решено отказаться в пользу интерфейсов. Практически всегда можно обойтись без использования данного механизма. Однако, если такая необходимость все-таки возникла, то, для разрешения конфликтов использования наследованных методов с одинаковыми именами, возможно, например, применить операцию расширения видимости — «::» — для вызова конкретного метода конкретного родителя.

Попытка решения проблемы наличия одинаковых имен методов в предках была предпринята в языке Эйфель, в котором при описании нового класса необходимо явно указывать импортируемые члены каждого из наследуемых классов и их именование в дочернем классе.

Большинство современных объектно-ориентированных языков программирования (C#JavaDelphi и др.) поддерживают возможность одновременно наследоваться от класса-предка и реализовать методы нескольких интерфейсов одним и тем же классом. Этот механизм позволяет во многом заменить множественное наследование — методы интерфейсов необходимо переопределять явно, что исключает ошибки при наследовании функциональности одинаковых методов различных классов-предков.

studfiles.net

Оставить комментарий

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *