Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lab_cpp.doc
Скачиваний:
10
Добавлен:
07.06.2015
Размер:
2.81 Mб
Скачать

Ход работы

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

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

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

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

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

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

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

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

  1. Зачем используются конструкторы и деструкторы?

  2. Какое имя имеет конструктор и деструктор?

  3. Сколько конструкторов и деструкторов может быть в классе?

  4. Можно ли выполнить инициализацию данных-членов без конструктора?

  5. Назовите отличия конструкторов и деструкторов от других функций

  6. Можно ли явно вызвать конструктор и деструктор?

  7. Можно ли передать параметры в конструкторы, использовать параметры по умолчанию?

  8. Как определить вызываемый конструктор, если их несколько?

  9. Что такое конструктор по умолчанию, конструктор копии?

  10. Приведите синтаксис объявления, определения и использования конструкторов, какие альтернативные варианты допустимы?

  11. Объясните приведенные примеры.

  12. Для чего необходимы оператора new и delete.

  13. Когда вызываются деструкторы для локальных и глобальных переменных

  14. Как происходит вызов деструкторов при выходе из программы, при вызове функций ехit(), abord()?

Лабораторная работа №22 Использование наследования для создания иерархии классов (2 часа)

Цель работы: получить навыки в использовании наследования для создания производных классов при простом наследовании.

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

При объявлении производного класса D перечисляются базовые классы В1, В2 ... в разделяемом запятой "базовом_списке". Cинтаксис объявления производного класса.

сlass <Имя_класса_D>:<Базовые_классы> {<список_элементов>};

При объявлении класса D перед классами в базовом списке вы можете задать спецификатор доступа public, или private, или protected.

class D : public B1, private B2, ... {

...

};

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

Если D представляет собой объявление класса (class), то по умолчанию используется private, а если D - объявление структуры (struct), то public.

Класс D наследует все элементы базовых классов. (Переопределенные элементы базовых классов наследуются и при необходимости доступ к ним возможен при помощи переопределений области действия). D может использовать элементы базовых классов только с атрибутами public и protected.

Производный класс наследует атрибуты доступа базового класса следующим образом:

  1. Если базовый класс указан в списке как public:

  • элементы public базового класса становятся элементами public производного класса.

  • элементы protected базового класса становятся элементами protected производного класса.

  • элементы private базового класса остаются private для производного класса.

  1. 2. Если базовый класс protected:

  • элементы базового класса общедоступные (public) и защищенные (protected) становятся защищенными (protected) элементами производного класса.

  • элементы private базового класса остаются для произвольного класса private.

  1. 3. Если базовый класс private:

  • общедоступные (public) и защищенные (protected) члены базового класса становятся частными (private) элементами производного класса.

  • элементы private базового класса остаются для производного класса private.

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

class X : A { // класс X является производным от класса А (простое

// наследование), причём по умолчанию спецификатор - private A

}

class Y : B, public C { // класс Y является производным (множественное

// наследование) от B и C. По умолчанию - private B, спецификатор для С- public

}

struct S : D { // struct S - производная от D, по умолчанию для структур

// struct - public D

..,

}

struct T : private D, E { // struct T является производной (множественное

// наследование) от D и E. Спецификатор для D – private D. По умолчанию,

// E - public E

}

Действие спецификаторов доступа к элементам базовых классов при наследовании можно скорректировать при помощи оператора разрешения области видимости (::) в разделах public или protected для производного класса. Например:

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

int a; // по умолчанию

// private

public:

int b, c;

int Bfunc(void);

};

class X : private B { // теперь члены базового класса // В::a, b, c и B func() - стали private в классе //наследнике Х. Переменная а в Х недоступна

int d; // по умолчанию private

public:

B::c; // переменная c была private; теперь она public:

int e;

int Xfunc(void);

};

int Efunc(X& x); // внешняя по отношению к классам В и Х, требует

// ссылку на объект х класса Х.

Функция Efunc() может использовать только имена членов класса Х с атрибутом public, например х.c, х.e и х.Xfunc.

Функция Xfunc() в X является функцией-членом, поэтому она имеет доступ:

  1. к собственным private и public элементам: d, e и Xfunc().

  2. к старшим private элементам базового класса В: b и Bfunc().

  3. Однако, Xfunc не имеет доступа к private относительно B элементу a.

  4. к переменной с класса В явно заданной public c помощью (::) – В::с.

Конструкторы базового класса должны объявляться с атрибутами public или protected. Причём: конструкторы производных классов обязательно вызывают конструкторы базовых классов.

Примеры:

class base1

{

int x;

public:

base1(int i) { x = i; }

};

class base2

{

int x;

public:

base2(int i) : x(i) {}

};

class top : public base1, public base2

{

int a, b;

public:

top(int i, int j) : base(i*5), base2(j+i), a(i) { b = j;}

};

В случае такой иерархии классов объявление top one(1, 2) приведет к инициализации base1 ::х значением 5, а base2 ::х значением 3. Методы инициализации могут комбинироваться друг с другом (чередоваться).

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

class X

{

int a, b;

public:

X(int i, j) : a(i), b(a+j) {}

};

Объявление X xobj (2.1) приведет к присваиванию xobj::a числа 2 и xobj::b числа 3.

Конструкторы базовых классов вызываются перед конструированием любых элементов производных классов. Значения данных-членов производного класса не могут изменяться и затем влиять на создание базового класса.

class base

{

int x;

public:

base(int i) : x(i) {}

};

class derived : base

{

int a;

public:

derived(int i) : a(i*10), base(a) {} // нельзя, т.к.

// конструктору base будет передано неинициализированное a

}

При внешнем определении конструктора derived он также вызывает конструктор базового класса

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

{

...

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]