Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Derived::derived(int i) : base(i)

Поиск

{

...

}

"Друзья" классов (friend)

Если в объявлении или определении функции в пределах класса Х используется спецификатор friend, то такая функция становится "другом" класса Х.

"Друг" F класса X - это функция или класс, который, не являясь функцией-элементом Х, имеет право доступа к элементам Х, включая разделы private и protected. Во всех прочих отношениях F() - это обычная с точки зрения области действия, объявления и определения функция.

Поскольку функция F() не является элементом Х, она не лежит в области действия Х и поэтому для Х хobj, *xptr; не может вызываться операциями выбора xobj. F() и xptr->F (где xobj - это объект класса Х, а xptr - это указатель на класс Х).

Дружественная функция, определенная в пределах класса (inline), подчиняется тем же правилам встраивания, что и функции-элементы класса. На дружественные функции не действуют спецификаторы доступа. Например:

Объявление класса Опpеделения для функций
class X { int i;// private friend void friend_func(X*, int); // friend_funcне является private, // хотя она и объявлена в разделе // private public: void member_func(int); }; void friend_func(X* xptr, int a) { xptr->i = a; } // доступ к private int i открыт void X::member_func(int a) { i = a; } //в функцию-член не нужно // передавать указатель или ссылку на // класс, т.к. доступ к ней // осуществляется через объект класса // операцией выбора (.)

X xobj; // объявление объекта xobj класса Х

Отметим различие в вызовах функций:

friend_func(&xobj, 6); // вызовбез имени объекта как обычная функция

xobj.member_func(6); // вызов с именем объекта класса

 

Можно сделать все функции класса Y дружественными для класса Х в одном объявлении:

class Y; //неполное объявление class X { friend Y;// класс Y является // дружественным для Х int i; void member_funcX(); }; class Y; { friend void X::member_funcX(); public: void fr_X1(X&); void fr_X2(X*); ... };

Функции fr_x1() и fr_x2(), объявленные в Y, являются дружественными для Х, хотя они и не имеют спецификаторов friend. Они имеют доступ к частным элементам Х (private), таким как i и member_funcX(). Кроме того, отдельные функции-члены класса Х также могут быть дружественными для класса Y.

"Дружественность" классов не транзитивна: если X является дружественным для Y, а Y - дружественный для Z, это не означает, что X - дружественный Z. Однако, "дружественность" наследуется.

 

Ход работы

1 Изучить теоретические сведения.

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

3 Разработать алгоритм решения задачи и программу.

4 Набрать программу на компьютере и устранить ошибки.

5 Получить результат.

6 Оформить отчет.

7 Подготовиться к защите лабораторной работы, изучив контрольные вопросы по данной теме.

 

Требования к содержанию отчёта приведены в лабораторной работе №1.

 

Контрольные вопросы для подготовки и самостоятельной работы

1 Что означает оператор (::)?

2 Что означает понятие наследования?

3 Какой класс называется базовым?

4 Какой класс является наследником?

5 Сколько базовых классов может быть у производного класса?

6 Может производный класс быть базовым?

7 Можно ли задавать спецификаторы для базовых классов при наследовании (объявление произвольного класса)?

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

9 В чём разница между простым и множественным наследованием?

10 Что означает выражение «неполное объявление» класса?

11 Можно ли уточнить доступ к членам базового класса в производном классе? Как это осуществляется?

12 Какие функции называются друзьями класса?

13 Как объявляются и определяются функции–друзья класса?

14 Может ли класс быть дружественным?

15 Могут ли два класса быть друзьями друг другу?

16 Можно ли из класса-наследника получить доступ к private части базового класса, если спецификатор доступа при наследовании private?

 

Таблица 22.1 - Варианты понятий для базовых классов

Вариант Понятие Вариант Понятие
  Растения   Мебель
  Животные   Строения
  Небесные тела   Мосты
  Спортивные соревнования   Бритвы
  Печатная продукция   Принтеры
  Промышленное производство   Плоттеры
  Телефоны   Разъёмы электрические
  Железнодорожно-транспортные средства   Манипуляторы для ввода информации
  Автомобильный транспорт   Устройства записи информации
  Осветительные приборы   Сканеры
  Средства связи   ЭВМ
  Телевизоры   Нагревательные устройства
  Корабли   Устройства передачи крутящего момента
  Мебель мягкая    

Лабораторная работа №23

Использование виртуальных и указателей для работы с объектами классов

(2 часа)

Цель работы: изучить и научиться использовать виртуальные функции в языке С.

Теоретические сведения

Виртуальные функции-члены объявляются в классе c ключевым словом virtual.

Если базовый класс (БК) base содержит виртуальную функцию (virtual) vf () и производный класс (ПК) derived также содержит эту функцию, то при вызове функции vf() для объекта базового класса мы получим base:: vf(), а для объекта производного класса мы получаем derived::vf(). Например:

Базовый класс Производный класс  
struct base {….. virtual void vf (void); void f (void); }; base_1 class {… public: virtual void vf(void)=0 void f(void); }; struct derived: public base {….. virtual void vf (void); // virtualв последнем // ПК можно опустить void f (void); };   derived d; //объект производ- // ного класса d.vf(); //вызов функции класса d // erived::vf() d.f(); //вызовфункции класса // derived::f() base* bp = &d; //указатель на // БК адресует объект ПК bp->vf (); //вызов виртуальной // функцииderived::vf() bp->f (); //вызов функции-члена // класса base // base:: f()

Тип объектов классов с виртуальными функциями определяется во время выполнения программы.

Поэтому при вызовах с помощью указателя bp на БК функций vf() и f() для объекта ПК с именем d вызываются, соответственно, derived::vf(), но base::vf(). В ызов нужной виртуальной функции vf() зависит от типа объекта, для которого она вызывается (derived d), в то время как вызов невиртуальной функции f() зависит только от типа указателя (base*bp), адресующего данный объект.

Если производный класс содержит функцию с тем же именем, что и имя виртуальной функции в базовом классе, то они должны иметь один и тот же тип. Функция vf() в ПК от БК, в котором содержится виртуальная функция vf(), также считается виртуальной. Виртуальная функция может быть определена в базовом классе. Виртуальную функцию, которая уже определена в базовом классе, в производном классе можно не определять. В этом случае при использовании указателя на БКдляадресацииПКпри всех обращениях используется функция, определенная в базовом классе. Если виртуальная функция в классе заканчивается нулём (=0), то она называется чистой виртуальной функцией. Чистая виртуальная функция не имеет определения в базовом классе, но определяется в производных. Класс, содержащий хотя бы одну такую функцию, называется абстрактным. Нельзя создать объект абстрактного класса.

Виртуальные базовые классы

При множественном наследовании базовый класс не может задаваться в производном классе более одного раза. Однако, базовый класс можно передавать производному классу более одного раза косвенно:

class B {... }; class D: B, B {... }: // недопустимо class X: public B {... }; class Y: public B {... }; class Z: public X, public Y {... }; // допустимо

В данном случае каждый объект класса Z будет иметь два подобъекта класса В. Для устранения этой проблемы к спецификатору базового класса добавляют ключевое слово virtual. Например:

 

class X: virtual public B {... }; // теперь В является виртуальным базовым

классом

class Y: virtual public B {... };

class Z: public X, public Y {... } // класс Z имеет только один подобъект класса В.

 

Виртуальные деструкторы

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

class color {... public: virtual ~color(); // виртуальный // деструктор для класса color }; class red: public color {... public: virtual~red(); // деструктор для red // также является виртуальным };


Поделиться:


Последнее изменение этой страницы: 2016-04-26; просмотров: 313; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.217.193.85 (0.006 с.)