книга (И.А. Волкова, А.В. Иванов, Л.Е. Карпов - Основы объектно-ориентированного программирования. Язык программирования С++), страница 12
Описание файла
Файл "книга" внутри архива находится в папке "И.А. Волкова, А.В. Иванов, Л.Е. Карпов - Основы объектно-ориентированного программирования. Язык программирования С++". PDF-файл из архива "И.А. Волкова, А.В. Иванов, Л.Е. Карпов - Основы объектно-ориентированного программирования. Язык программирования С++", который расположен в категории "". Всё это находится в предмете "практикум (прикладное программное обеспечение и системы программирования)" из 4 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 12 страницы из PDF
наследование — открытое.return 0;}При необходимости открытого наследования членов базового типа,если тип-наследник описывается с использованием класса, следует явноуказывать квалификатор public:class C: public A{int z;};ЗамечаниеВ других системах программирования, связанных, например, с языком Java, непредусмотрен квалификатор доступа при наследовании, так как в языке Javaпредусмотрен только открытый способ наследования.Защищенный вид доступа (protected) означает, что члены базового типав типе-наследнике доступны только для методов своего (базового) типа, а72Одиночное наследованиетакже для методов производного типа.
Во всех остальных случаях они ведутсебя так же, как члены с закрытым видом доступа (private).Пример:struct A{int x,y;};class B: protected A{int z;public:void putx (int ap){x = ap;}};int main(){B b1;b1.putx(1);. . .return 0;}Ограничение видимости при наследовании ограничивает манипуляциис членами базового типа только в объектах типа-наследника и его потомках.Поэтому при преобразовании указателя типа-наследника к указателю наобъекты базового типа работа с объектом осуществляется в соответствиис правилами видимости для базового класса.Пусть указатель на объект типа-наследника при защищенном наследовании преобразован к указателю на объекты базового типа. Тогда работас объектом типа-наследника с использованием указателя на объекты базового типа происходит в соответствии с правами доступа для базового типа(как уже было указано, через такой указатель виден не весь объект типа-наследника, а только его часть, соответствующая базовому типу):struct A{int x; int y;};struct B: A{int z;};class C: protected A{int z;};int main(){A a;A* pa;B b;C c;C* pc = &c;73Одиночное наследованиеb.x = 1;//pc -> z;b.y = 2;//pc -> x;b.z = 3;pa = (A*)pc;a = b;pa -> x=4;return 0;// ошибка: доступ к закрытому полю// ошибка: доступ к закрытому полю// см.
примечание далее.// правильно: поле A::x - открытое}ПримечаниеТак как в данном примере наследование — защищенное, то при присвоенииуказателя производного типа указателю базового типа требуется явное преобразование (pa=(A*)pc;). При открытом наследовании возможно простоеприсвоение указателей (pa=pc). Это связано с тем, что указатель кроме адресасодержит информацию об объекте.
При защищенном наследовании изменяется не только состав членов класса, но и права доступа.Далее вопросы наследования будут рассмотрены на основе классов.При необходимости данные сведения могут быть переработаны для структурс учетом области доступа и квалификатора доступа при наследованиив структурах по умолчанию.10.4. Закрытое (private)наследованиеЗакрытые члены базового класса недоступны напрямую с использованиемдополнительных методов класса-наследника (при любом способе наследования). Работа внутри класса-наследника с такими получаемыми закрытымичленами базового класса возможна только с использованием открытыхи защищенных методов базового класса.Закрытые и защищенные получаемые методы недоступны для манипулирования с объектом вне класса.
Они могут использоваться как подпрограммы другими методами класса.При закрытом наследовании открытые и защищенные члены базовогокласса (любые) доступны только внутри производного класса и недоступныизвне (через объекты производного класса), как и его собственные закрытыечлены.Таким образом, приведенная таблица показывает вид доступа для членов в типе наследнике для типа наследника следующего уровня. Но, для текущего типа-наследника доступность зависит от вида доступа в базовом типе.Пример:class X1{int ix1;public:74Одиночное наследование};int f1() { . . . }.
. .class Y1: protected X1{. . .};class Z1: public Y1{. . .};class X2{protected:int ix2;public:int f2 () { . . . }. . .};class Y2: X2 {. . .};class Z2: public Y2 {. . .};В классе Y1 переменная ix1 недоступна непосредственно, так как онав базовом классе X1 находится в закрытой области. Однако она может бытьиспользована в функции f1(). в то же время функция f1() не может использоваться в качестве внешнего метода по отношению к объекту, созданному наоснове класса Y1, так как она находится в защищенной области класса Y1. Этоже остается справедливым и для класса Z1.
в классе Y2 переменная ix2,в отличие от переменной ix1 в классе Y2, доступна непосредственно. В классеZ2 переменная ix2 становится недоступной для непосредственного использования, так же, как и переменная ix1 в классе Z1. Другие отличия классов Z1и Z2: в отличие от функции f1() в классе Z1, функция f2() в классе Z2 доступнав классе Z2 качестве внутренней подпрограммы, только для функций, унаследованных из класса Y2, так как в классе Y2 она находится в закрытой области.Закрытое наследование целесообразно в том случае, когда меняетсясущность нового объекта.Пример:Базовый класс описывает фигуры на плоскости и имеет методы вычисления площади фигур, а класс-наследник описывает объемные тела, например, призмы с основанием — плоской фигурой, описываемой базовымклассом.
в этом случае объем тела, описываемого классом-наследником,вычисляется умножением площади основания на высоту. При этом не имеетзначения, каким образом получена площадь основания. Кроме того, методыработы с объемными объектами отличны от методов работы с плоскимиобъектами. Поэтому в данном случае не имеет смысла наследование методовбазового класса для работы с объектами, описываемыми классом-наследником:#include <iostream>75Одиночное наследованиеusing namespace std;class twom{double x,y;public:twom ( double x1=1, double y1=1 ): x(x1), y(y1) {}double sq(){return x*y;}};class thm: private twom{double z;public:thm ( double x1 = 1, double y1 = 1,double z1 = 1): twom(x1,y1), z(z1) {}double vol(){return sq()*z;}};int main(){thm t1 ( 1, 2, 3 );double d1;d1 = t1.vol();cout << "vol= " << d1 << '\n';return 0;}Таким образом, закрытое наследование несколько напоминает композицию объектов, когда подобъект находится в закрытой области.
Все женеобходимо помнить, что наследование — это совсем другая концепция ассоциирования классов, по многим своим свойствам отличная от агрегации,даже в ее строгом варианте (композиции).10.5. Перекрытие именВ производном классе могут использоваться имена членов класса, перекрывающие видимость таких же имен в базовом классе (overriding). При перекрытии имен при работе с объектом через указатель будет исполняться тотметод, который содержится в классе, используемом в объявлении указателя,независимо от типа объекта, на который указывает указатель.Пример:#include <iostream>using namespace std;class A{public:void f ( int x ){cout << "A::f" << '\n';}76Одиночное наследование};class C: public A{public:void f ( int x ){cout << "C::f" << '\n';}};int main(){A a1;A* pa;C c1;C* pc;pc = &c1;pc -> f(1); // C::fpa = pc;pa -> f(1); // A::f — несмотря на то, что pa указывает// на объект c1 типа класс C.pc = (C*)& a1; // Небезопасное преобразованиеуказателя// на объект базового класса к указателю// на объект производного класса (данное// преобразование должно объявляться// явно, иначе — ошибка).pc -> f(1); // C::f — несмотря на то, что pa указывает// на объект а1 типа класс А,// в общем случае такой вызов некорректен.return 0;}Члены базового класса с именами, совпадающими с именами членовпроизводного класса, доступны в производном классе.
Для доступа к нимнеобходимо указывать квалификатор (имя базового класса) с использованиемоперации «::», так как данные члены находятся в доступной области видимости, которая не совпадает с текущей областью видимости. Также методбазового класса доступен через указатель класса-наследника при условиииспользования квалификатора.Пример:#include <iostream>using namespace std;class A {public:void f ( int x ) { cout<<"A::f"<<'\n'; }};class C: public A{public:void f ( int x ){cout << "C::f" << '\n';}void g(){f (1);A::f (1);}};77Одиночное наследованиеint main(){C c1;C* pc;pc=&c1;pc->A::f (1); // вызов метода базового класса с// использованием указателя// класса–наследника.pc->f (1);pc->g ();return 0;}Таким образом, при перекрытии методы базового класса не «затираются» в классе-наследнике.
Они доступны через квалификатор.10.6. Наследование и повторноеиспользование кодаПовторное использование кода предполагает выделение некоего фрагментакода в процедуру, которая может вызываться из различных модулей программы.Наследование — наиболее удобный механизм для повторного использования кода. Суть наследования состоит в том, что в иерархии классов выделяется базовый класс, реализующий функциональность, общую для всехклассов-наследников. Классы-наследники наследуют эту функциональность,а также при необходимости реализуют некоторые дополнительные функции,специфические для этих классов-наследников.В случае открытого (public) наследования открытые методы базовогокласса, остаются открытыми методами классов-наследников, таким образом,интерфейс базового класса расширяется в классе-наследнике. в случае закрытого (private) наследования методы базового класса не могут использоваться в классе-наследнике в качестве методов интерфейса, но могут использоваться как подпрограммы для выполнения некоторых базовых действий (их можно вызывать из других доступных методов производного класса).Поэтому закрытое наследование называется наследованием реализациив противоположность наследованию интерфейса (открытое наследование).Наследование реализации можно эффективно применять при построении схем отношений в сложных системах.