|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция |
Производные классыВ С++ базовым может быть любой класс. По синтаксису это обычные классы. Class Shape{ public: int x,y; int color; void Move (int dx, int dy); }; Void Shape::Move (int dx, int dy){ x+=dx; y+=dy; } При определении производных классов необходимо указывать список базовых классов. Синтаксис С++ допускает несколько базовых классов для одного производного. Этот случай называется множественным наследованием, но в большинстве ситуаций – базовый класс 1. Реализуем производные классы для нашей иерархии(системы классов связвных наследованием): Class Circle: public Shape { Public: int r; } Class Triangle: public Shape { Public int dx[3], dy[3]; }
Покажем, что элементы заимствуются: Void f(){ Circlec; c.x=100; c.y=200; c.Move(5,-10); c.r=100;}
Метод Move относящийся к базовому классу корректно работает для для обьектов производного класса. Это обеспечивается за счет особой организации памяти. Новые поля производных классов добавляются после полей базовых классов. Это гарантирует работоспособность наследованных методов: они обращаются только к началу памяти объекта и, как правило, ничего не знают о его фактическом типе. В нашем случае одна строка производного класса заимствует 3 поля и один метод из базового. Иерархия классов также реализует идею расширяемости в 2-ух направлениях: 1) Т.к. базовый класс ничего не знает о производных, то существовать любое количество производных классов которые можно добавлять без перекомпиляции кода. 2) В правильно спроектированной иерархии функциональность базовых классов можно расширять без модификации исходных текстов производных классов. Class Shape{ public: int x,y; int color; void Move (int dx, int dy); void SetTo (int x, int y); }; Void Shape:: SetTo (int x, int y) { X=X; Y=Y; }
При рассмотрении функции базового класса как правило сохраняется совместимость.
61. Реализация производных классов. Реализация производных классов для нашей иерархии.(классы геометрических фигур см. Вопрос 59.) Иерархия – это система классов, связанных наследованием. Class circle: public shape; (public shape – список базовых классов) { public: int r; } Class triangle: public shape; (public shape – список базовых классов) { public: int dx[3], dy[3]; }; Покажем, что элементы заимствуются: Void f() { circle c; C. X=100; c. Y=200; c. Move(5, - 10); c. R=100; triangle t; t. X=180; } Метод move относят к базовому классу. Корректно работает для объекта производного класса. Это обеспечивается за счет особой организации памяти.
Новые поля производных классов добавляются после полей базовых классов, что гарантирует работоспособность у наследованных методов: они обращаются только к началу данного(памяти) объекта и,как правило, ничего не знают о его фактическом типе. Замечание: пример хорошо показывает принцип повторного использования кода. Одна строка в производном классе заимствует 3 поля и метод из базового класса. Иерархия классов также реализует идею расширяемости в 2-х направлениях: 1. Т.к. Базовый класс ничего не знает о производных, то может существовать любое количество производных классов, которые можно добавлять без перекомпиляции кода базового класса. 2. В правильно спроектированной иерархии функциональность базовых классов можно расширять без модификации исходных текстов производных классов. Понадобится перекомпиляция Class shape { public: int x,y; int color; void move(int dx, int dy); void setto (int x, int y); } Void shape:: setto(int x, int y); { x=x; y=y; } При расширений функций базового класса, как правило, сохраняется совместимость.
62. Конструкторы и деструкторы при наследовании. Конструктор – метод, который вызывается при создании объекта. Имя конструктора всегда совпадает с именем класса, конструктор никогда не возвращает значение. Деструктор – это метод, который вызывается компилятором, когда завершается время жизни объекта. Имя деструктора совпадает с именем класса, предваряется значком «~», и деструктор не имеет параметров и возвращаемого значения. Пара классов базовый-производный нуждается в конструкторах и деструкторах. Компилятор С++ гарантирует вызов конструктора и деструктора в иерархии, если они есть. В иерархии конструкторы вызываются от базовых классов к производным(деструкторы в обратном порядке). Это связано с тем, как конструируются наборы полей.
Сначала будет вызван конструктор для Shape, а затем для Circle. Это нужно т.к. В конструкторе производного класса может понадобится ср-ва базового класса, а они обычно требуют, чтобы эл-ты базового класса были уже сконструированы. Если в базовом классе есть конструктор по умолчанию и больше ничего не делать, то будет вызван этот конструктор. Если никаких конструкторов в базовом классе нет, то никаких особых усилий не нужно. Если в базовом классе есть конструкторы с параметрами или необходимо сделать его вызов, то для параметров нужно представить значения. Синтаксис похож на такой же случай в композиции. Class Shape { public: int x,y; int color; void Move(int dx, int dy); void setto (int x, int y); Shape(int X,int Y,int color); }; Class Circle: public shape { public: int r; Cirxle (int X, int Y, int color, int R); } Circle (int X, int Y, int color, int R): Shape (x,y,color) { r=R } Class Circle: public shape { public: int r; Circle(int R); }; Circle (int R): shape (0,0,0xff) { r=R; } В данном примере в одном и том же классе Circle могут существовать оба варианта конструктора. В случае, если нужен конструктор копирования, также есть несколько ситуаций. Они формируются так же. В этом случае 1-ая ситуация(когда вызывается конструктор по умолчанию базового класса) является весьма сомнительно, но допустимой. Предпочтительнее реализовать ситуацию № 3: Class Shape { public: int x,y; int color; void Move(int dx, int dy); void setto (int x, int y); Shape(Shape &S); }; Class Circle: public shape { public: int r; Cirxle (Circle &e); } Circle:: Circle (Circle &e); Shape (e); } //? Деструкторы в иерархии классов вызываются автоматически от производных классов. 63. Иерархия классов. При использовании наследования в C++ для порождения одного класса из другого возможны ситуации, когда вы порождаете свой класс из класса, который уже, в свою очередь, является производным от некоторого базового класса. Производный классы в свою очередь могут быть базовыми. Базовых классов может быть несколько. Это позволяет строить весьма сложные иерархии.
Class Temporary {}; Class Emplose {}; Class Secretary: public Emplose {}; Class tsec: public Secretary, public Temporary {}; Class Manager: public Employee {}; Class Director: public Manager{}; Class Consultant: public Manager, public Temporary {}; ООП позволяет отображать весьма сложные взаимосвязи между понятиями, но это вопрос проектирования, а не кодирования. 64. Управление доступом при наследовании. При наследовании рекомендуется помнить о сокрытии данных. Для наследования есть дополнительные средства управления доступом: 1. Модификатор protected -> когда он использ. Внутри класса, соотв. Эл-ты становятся видны производным классам, но не доступны из внешнего кода; Private – только классу.; Public – общедоступный. 2. Модификатор доступа при наследовании, который позволяет ограничить доступ когда конструируется иерархия. Class Circle: public Shape { Этот модификатор предназначен для того, чтобы ограничить видимость эл-тов базового класса. Фактическая доступность образуется как сочетание модификатора доступа при наследовании и модификаторов эл-тов в классе.
Внутри результирующий модификатор эт-та базового класса, который он получает в производном классе. Class A { public: void B(); }; Class C: protected A { }; Класс А наследуется классов С с модификатором protected. Элементы класса А будут доступны только производным от С классам. Рекомендуется использовать модификаторы наследования в след. Ситуациях: 1. Public –класс наследуется в составе основной иерархии класса программ. Наиболее часто используемый случай. 2. Protected – предлагается использовать когда стыкуется между собой разные ООП-библиотеки. Альтернативой могут выступать шаблоны патерного проектирования такие как Proxy. 3. Private – базовый класс используется для реализации функции производного. Альтернативой явл. Композиция.
Поиск по сайту: |
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.009 сек.) |