Добавил:
ИВТ (советую зайти в "Несортированное") Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
1
Добавлен:
23.11.2024
Размер:
207.36 Кб
Скачать

Лабораторная работа № 4 (БДЗ 1)

Наследование классов, виртуальные функции

Цель работы: изучить одну из базовых концепций ООП – наследование классов в С++, заключающуюся в построении цепочек классов, связанных иерархически.

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

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

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

Что дает наследование?

  1. Возможность расширить возможности класса без дублирования кода.

Пример: точка(базовый класс) -> круг(наследует точку) -> конус(наследует круг)

  1. Наследование удобно при модернизации уже существующих программ.

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

  1. Однотипность работы с общей частью - все наследники поддерживают интерфейс базового класса.

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

Например, класс child объявляет себя наследником класса parent:

parent – базовый класс

child – производный класс.

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

Формат наследования:

сlass имя_базового_класса: доступ имя_производного_класса

{ тело производного класса}

Доступ (тип наследования): public, private, protected

Если доступ при наследовании не указан, то действуют стандартные умолчания:

  • для типа class - доступ private

  • для типа struct - доступ public

Пример1: Транспортные средства

//--- БАЗОВЫЙ КЛАСС «Транспорт»

class transport

{ // общие данные для всех наследников

int k_num; // число колес

int p_num; // max число пассажиров

public: // интерфейс базового класса

void set_k (int num)

{ k_num=num;}

void set_p (int num)

{ p_num=num;}

int get_p()

{return p_num;}

int get_k()

{return k_num;}

}; //------------- конец определения класса transport

После того, как дано определение транспортного средства (базового класса), его можно использовать для наследников определения конкретных транспортных средств.

//-----ПРОИЗВОДНЫЙ КЛАСС «Вагон»

class g_avto : public transport

{ int gruz; // грузоподъемность

public :

void set_gruz (int q)

{ gruz=q;}

void show(); //прототип ф-ции

}; //------------- конец определения класса g_avto

Класс g_avto наследует все содержимое класса transport, то есть все поля данных и все функции. Кроме того, добавлено поле gruz, а также функции, необходимые для его поддержки - set_gruz () и get_gruz ().

Производный класс:

  • не имеет доступа к закрытым элементам базового класса (k_num, p_num)

  • имеет доступ к открытым элементам (все функции)

//--ПРОИЗВОДНЫЙ КЛАСС «Автомашина»

enum car {maz, gazel, jeep};

class mobile:public transport

{car type;

public:

void set_type (car t )

{ type=t;}

void show();

}; //------------- конец определения класса mobile

// Реализация методов для производных классов.

void g_avto:: show()

{cout<< "\nХарактеристики вагона :\n"\

<<"число пассажиров\t"<<get_p()<<endl\

<< "грузоподъемность: " << gruz;

}

void mobile:: show()

{cout<< "\n Характеристики автомобиля :\n "<< "тип - ";

switch (type)

{

case maz : cout<< "фура\n";break;

case gazel : cout<< "грузовик\n"; break;

case jeep : cout<< "джип\n";

}

cout<< "число колес: "<<get_k()<<endl <<"Максимальное число пассажиров: " <<get_p()<<endl;

}

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

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

int _tmain(int argc, _TCHAR* argv[])

{ g_avto w;

mobile q;

// инициализация объектов w, q

w.set_p (39); w.set_gruz(5000);

q.set_p(3); q.set_k(6); q.set_type(maz);

// вывод на экран

cout<<"\n--------------------\n";

.show();

cout<<"\n--------------------\n";

q.show();

system ("pause");

return 0;

}

Результат выполнения программы:

Характеристики вагона :

Число пассажиров : 39

Грузоподъемность : 50000

Характеристики автомобиля :

Тип : фура

Максимальное число пассажиров : 3

Часто базовый класс (БК) создаётся только для того, чтобы задать общую часть данных для некоторой группы классов. В этом случае функции БК являются вспомогательными («техническими»), они обслуживают нужды «наследников» (в нашем случае – обеспечивают доступ к закрытым данным). В этом случае объектов базового класса не создается.

Конструкторы и деструкторы при наследовании.

При наследовании возникает два вопроса :

• когда вызываются конструкторы и деструкторы базового и производного классов?

• Как передаются параметры конструкторов базового класса?

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

#include "stdafx.h"

#include <iostream>

using namespace std; class base

{ int p_b;

public:

base()//--------- base-конструктор

{cout<< "Создание объекта base\n";}

~base()

{cout<<"Уничтожение объекта base\n";}

};//-- конец определения базового класса

class derived : public base

{ int p_d;

public:

derived() //------- derived-конструктор

{cout<< "Создание объекта derived \n";}

~derived()//--------- деструктор

{cout<< "Уничтожение объекта derived\n";}

};//-- конец определения произв. класса

int _tmain(int argc, _TCHAR* argv[])

{derived ob; // создание объекта

system ("pause");

return 0;

}

Результат выполнения программы :

Создание объекта base

Создание объекта derived

Уничтожение объекта derived

Уничтожение объекта base

Соседние файлы в папке _Задания к лабам