русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Базовый и производные классы


Дата добавления: 2015-07-09; просмотров: 6342; Нарушение авторских прав


Производные классы являются эффективным средством для расширения функциональных возможностей существующих классов без перепрограммирования и повторной компиляции существующих программ.

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

тип_класса имя_производного_класса : список[ модификатор_доступа имя_базового_класса] {определение_производного_класса};

При создании объектов производного класса сначала автоматически вызываются конструкторы базовых классов согласно списку базовых классов в объявлении производного класса, а затем конструктор производного класса. Конструкторы базовых классов вызываются независимо от того, перечислены они явно в конструкторе производного класса или нет. Объекты разрушаются в порядке, обратном их созданию, т.е. вначале вызывается деструктор производного класса, а затем базового.

Один класс может быть базовым для нескольких производных, производный класс может быть, в свою очередь, базовым для какого-либо класса и т.д. Если производный класс имеет несколько базовых, то такое наследование называется множественным. Иногда базовый класс называют родительским, а производный – потомком.

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

Если доступ к собственным компонентам производных классов определяется обычным образом, то на доступ к наследуемым компонентам влияет, во-первых, атрибут доступа в базовом классе и, во–вторых, модификатор доступа (public / private), указанный перед именем базового класса в конструкции определения производного класса.



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

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

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

 

class Based {

/* ...*/

public:

virtual int fb(){return 3;}

/* ...*/

};

class Derived:public Based {

/* ...*/

int fb() {return 5;}

/* ...*/

};

Виртуальная функция класса может вызываться обычным образом - как член этого класса через его объект. Но тогда никаких преимуществ по сравнению с не виртуальной функцией ее применение не приносит. Причина, по которой виртуальные функции так широко используются, состоит в том, производный класс, объект которого нам нужно создать в какой-то момент выполнения программы, определяется именно в этот момент, а не на стадии компиляции программы. Для реализации этой возможности обращения к виртуальным функциям производится через указатель на базовый класс. Т.е. сообщения передаются как указатели, которые указывают на объект вместо прямой передачи объекту.

В настоящей лабораторной работе можно использовать атрибут virtual в базовом классе и вызывать такие функции обычным образом; правильный вызов подробно рассматривается в следующей лабораторной работе.

Виртуальная функция в базовом классе может быть нулевой. В нашем случае

virtual int fb( )=0;

В этом случае базовый класс называется абстрактным; объект такого класса создать нельзя, только указатель на объект. Мало того, если в каком-либо производном классе эта функция отсутствует, то от такого класса тоже нельзя создавать объекты (в C# такие классы называются бесплодными).

Пример выполнения работы.

Создать базовый класс Vehicle. На его основе реализовать классы Car (автомобиль) и Lorry (грузовик). Классы должны иметь возможность задавать и получать параметры средств передвижения (цена, максимальная скорость, год выпуска и т.д.). Наряду с общими полями и методами, каждый класс должен содержать и специфичные для него компоненты.

В базовом классе ограничимся двумя общими полями типа protected: ценой и годом выпуска. Кроме того, введем идентификатор типа ID: 'C' для автомобилей и 'L' для грузовиков. Так как поля класса должны быть защищены, то введем общие методы для установления значения полей.

//Базовый класс

class Vehicle{

protected:

int price;//цена

int year; //год выпуска

char ID; // признак

public:

//Устанавливаем цену, год выпуска и идентификатор

void SetVehicle(int _price, int _year)

{price=_price; year=_year;}

void SetID(char _ID)

{ID=_ID;}

};

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

class Lorry:public Vehicle{

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

public:

//Устанавливаем грузоподъемность

void SetCapacity(int _capacity)

{capacity=_capacity;}

};

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

class Car: public Vehicle{

int speed; // скорость

public:

//устанавливаем скорость

void SetSpeed(int _speed){speed=_speed;}

};

/*Собственно, все. Теперь в main можно создавать объекты Lorry и Car и вводить данные, например, так:

Lorry lo;

lo. SetVehicle(10000, 2012);

lo. Capacity(5000);

Очевидно, что в программе мы будем иметь дело не с 1-м, а с несколькими автомобилями, т.е. с массивом, который надо организовать и обрабатывать. Чтобы не заставлять клиента заниматься этим, введем класс Garage, включив в него разработанные нами типы. ( см. замечания к работе 1).

Вот как он может выглядеть (продолжаем программу): */

class Garage{

int n; // Количество машин в гараже

Lorry *lor; // указатели на классы

Car *car;

public:

//Конструкторы

Garage(int _n)// для создания массива грузовиков

{n=_n; lor=new Lorry[n]; car=0;}//В объекте, создаваемым этим //конструктором указатель lor значимый,a car=0 – см. деструктор класса

 

//Второй конструктор в классе обязательно должен отличаться от первого списком //параметров

Garage(int _n, char _ID) // для создания массива автомобилей

{n=_n; car=new Car[n]; lor=0;} ;}//В объекте, создаваемым этим //конструктором указатель car значимый,a lor=0 – см. деструктор класса

// Ввод данных для автомобилей

void InCar()

{ int _price, _year, _speed; //Вспомогательные переменные

for(int i=0; i<n; i++)

{ cout<<"Input values price, year, speed for "<<i+1<< " Car" <<endl;

cin>>_price>>_year>>_speed;

car[i].SetVehicle(_price,_year);

car[i].SetSpeed(_speed);

car[i].SetID('C');

}

}

//Ввод данных для грузовиков

void InLorry()

{ int _price, _year, _capacity;

for(int i=0; i<n; i++)

{ cout<<"Input values price, year, capacity for "<<i+1<< "

Lorry"<<endl;

cin>>_price>>_year>>_capacity;

lor[i].SetVehicle(_price,_year);

lor[i].SetCapacity(_capacity);

lor[i].SetID('L');

}

}

// Деструктор

~Garage(){ if(car==0)delete[] lor;

if(lor==0)delete[] car;

}

};

//Теперь наш клиент приобретает совсем простой вид

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

{

Garage g1(2); //Объект - массив из 2-х грузовиков

g1.InLorry(); // Ввод данных

Garage g2(4,'C'); //Объект - массив из 4-х авто

g2.InCar();

return 0;

}

В классе Garage можно инкапсулировать все методы работы с объектами: сортировку, ввод-вывод в файл и т.п.

Я не утверждаю, что приведенный вариант класса Garage является идеальным. Возможно, этот класс можно было сделать наследником Lorry и Car. Может быть, решение было бы проще ( проверьте). Но дело в том, что у нас появилось бы множественное наследование, а его, по возможности, надо избегать. Впрочем, я не возражаю и против такого решения ваших задач.

 

Варианты заданий

 

1. Создать базовый класс CList (линейный однонаправленный cписок) с полями: указатели на начало списка, на его конец и на следующий элемент; информационная часть – целое число. В производных классах – CQueue (очередь) и CStack (стек) – должны быть определены методы вставки и удаления узла в соответствии с дисциплиной обслуживания соответствующего класса.

2. Описать базовый класс CString (Строка) и производные CStringBit (Битовая_строка) и CStringHex (Шестнадцетиричная_строка). (Описание класса см. вариант 9 в 1-й работе.) Строки первого подкласса могут содержать только двоичные символы, второго только шестнадцетиричные. Разработать методы ввода данных с проверкой допустимых символов. Содержимое строк рассматривается как двоичное или шестнадцетиричное число без знака. Разработать операции сравнения двух строк, сложения и вычитания. Создать класс, содержащий массив объектов производных классов в динамической памяти.

3. Создать абстрактный класс Point (точка). На его основе создать классы ColoredPoint и Line. На основе класса Line создать класс ColoredLine и класс PolyLine (многоугольник). Все классы должны иметь методы установки и получения значений всех координат, а также изменения цвета и получения текущего цвета. Создать класс Picture, содержащий массив объектов этих классов в динамической памяти. Предусмотреть возможность ввода и вывода характеристик объектов.

4. Создать абстрактный класс Figure. На его основе реализовать классы Rectangle (прямоугольник), Circle (круг) и Trapeze (трапеция) с возможностью вычисления площади, центра тяжести и периметра. Создать класс Picture, содержащий массив объектов этих классов в динамической памяти. Предусмотреть возможность ввода и вывода характеристик объектов.

5. Создать абстрактный класс Number c виртуальными методами, реализующими арифметические операции. На его основе реализовать классы Integer и Real. Создать класс Series (набор), содержащий массив объектов этих классов в динамической памяти. Предусмотреть возможность ввода и вывода характеристик объектов.

6. Создать абстрактный класс Body. На его основе реализовать классы Parallelepiped (прямоугольный параллелепипед), Cone (конус) и Ball (шар) с возможностью вычисления площади поверхности и объема. Создать класс Series (набор), содержащий массив объектов этих классов в динамической памяти. Предусмотреть возможность вывода характеристик объектов списка.

7. Создать абстрактный класс Currency для работы с денежными суммами. Определить в нем методы перевода в рубли и вывода на экран. На его основе реализовать классы Dollar, Euro и Pound (фунт стерлингов) с возможностью пересчета в центы и пенсы соответственно. Создать класс Purse (кошелек), содержащий массив объектов этих классов в динамической памяти. Предусмотреть возможность вывода общей суммы, переведенной в рубли, и суммы по каждой из валют.

8. Создать абстрактный класс Triangle (треугольник), задав в нем длину двух сторон, угол между ними, методы вычисления площади и периметра. На его основе создать классы, описывающие равносторонний, равнобедренный и прямоугольный треугольники со своими методами вычисления площади и периметра. Создать класс Picture, содержащий массив объектов этих классов в динамической памяти. Предусмотреть возможность вывода характеристик объектов списка и получения суммарной площади..

9. Создать абстрактный класс Solution (решение) с методами вычисления корней уравнения и вывода на экран. На его основе реализовать классы Linear (линейное уравнение) и Square (квадратное уравнение). Создать класс Series (набор), содержащий массив объектов этих классов в динамической памяти. Предусмотреть возможность ввода и вывода характеристик объектов списка..

10. Создать абстрактный класс Function (функция) с виртуальными методами вычисления значения функции y = f(x) в заданной точке х и вывода результата на экран. На его основе реализовать классы Ellipse, Hiperbola и Parabola. Создать класс Series (набор), содержащий массив/параметризованную коллекцию объектов этих классов в динамической памяти. Предусмотреть возможность вывода характеристик объектов списка.

11. Создать абстрактный класс Triad (тройка) с виртуальными методами увеличения на 1. На его основе реализовать классы Date (дата) и Time (время). Создать класс Memories, содержащий массив пар (дата-время) объектов этих классов в динамической памяти. Предусмотреть возможность вывода характеристик объектов списка и выборки самого раннего и самого позднего событий.

12. Описать абстрактный класс Element (элемент логической схемы), задав в нем числовой идентификатор, количество входов, идентификаторы присоединенных к нему элементов (до 10) и двоичные значения на входах и выходе. На его основе реализовать классы AND и OR — двоичные вентили, которые могут иметь различное количество входов и один выход и реализуют логическое умножение и сложение соответственно. Создать класс Sсheme (схема), содержащий массив объектов этих классов в динамической памяти. Предусмотреть вычисление значений, формируемых на выходах схемы по заданным значениям входов.

13. Описать абстрактный класс Element (элемент логической схемы) задав в нем символьный идентификатор, количество входов, идентификаторы присоединенных к нему элементов (до 10) и двоичные значения на входах и выходе. На его основе реализовать классы AND_NOT и OR_NOT — двоичные вентили, которые могут иметь различное количество входов и один выход и реализуют логическое умножение c отрицанием и сложение c отрицанием соответственно. Создать класс Sсheme (схема), содержащий массив объектов этих классов в динамической памяти. Предусмотреть вычисление значений, формируемых на выходах схемы по заданным значениям входов.

14. Описать абстрактный класс Trigger (триггер), задав в нем идентификатор и двоичные значения на входах и выходах. На его основе реализовать классы RS и JK, представляющие собой триггеры соответствующего типа. Создать класс Register (регистр), содержащий массив объектов этих классов в динамической памяти. Предусмотреть общий сброс и установку значений каждого триггера по заданным значениям входов.

15. Создать абстрактный класс Progression (прогрессия) с виртуальными методами вычисления заданного элемента и суммы прогрессии. На его основе реализовать классы Linear (арифметическая) и Exponential (геометрическая). Создать класс Series (набор), содержащий массив объектов этих классов в динамической памяти. Предусмотреть вывод общей суммы всех прогрессий.

16. Создать абстрактный класс Pair (пара значений) с виртуальными методами, реализующими арифметические операции. На его основе реализовать классы Fractional (дробное) и LongLong (длинное целое).В классе Fractional вещественное число представляется в виде двух целых, в которых хранятся целая и дробная часть числа соответственно. В классе LongLong длинное целое число хранится в двух целых полях в виде старшей и младшей части. Создать класс Series (набор), содержащий массив объектов этих классов в динамической памяти. Предусмотреть возможность вывода характеристик объектов списка и вывода общей суммы всех значений..

17. Создать абстрактный класс Integer (целое) с символьным идентификатором, виртуальными методами, реализующими арифметические операции, и методом вывода на экран. На его основе реализовать классы Decimal (десятичное) и Binary (двоичное). Число представить в виде массива цифр. Создать класс Series (набор), содержащий массив/параметризованную коллекцию объектов этих классов в динамической памяти. Предусмотреть возможность вывода значений и идентификаторов всех объектов списка и вывода общей суммы всех десятичных значений.

18. Создать класс Sorting (сортировка) с идентификатором последовательности, виртуальными методами сортировки, получения суммы и вывода на экран. На его основе реализовать классы Choice (метод выбора) и Quick (быстрая сортировка). Создать класс Series (набор), содержащий массив в динамической памяти. Предусмотреть возможность вывода идентификаторов и сумм элементов каждого объекта списка, а также вывода общей суммы всех значений.

19. Создать класс Pair (пара значений) с виртуальными методами, реализующими арифметические операции, и методом вывода на экран. На его основе реализовать классы Money (деньги) и Complex (комплексное число). В классе Money денежная сумма представляется в виде двух целых, в которых хранятся рубли и копейки соответственно. При выводе части числа снабжаются словами «руб.» и «коп.». В классе Complex предусмотреть при выводе символ мнимой части (i). Создать класс Series (набор), содержащий массив объектов этих классов в динамической памяти. Предусмотреть возможность вывода объектов списка.

20. Создать класс Worker с полями, задающими фамилию работника, фамилии руководителя и подчиненных и методами вывода списка обязанностей и списка подчиненных на экран. На его основе реализовать классы Manager (руководитель проекта), Developer (разработчик) и Coder (младший программист) с соответствующими методами. Создать класс Group (группа), содержащий массивы объектов в динамической памяти. Предусмотреть возможность вывода всех объектов списка и выборки по фамилии с выводом всего дерева подчиненных.

 

 

Контрольные вопросы

1. В чем заключается наследование одного класса другому? В чем разница в организации

наследования полей и методов?

2. Удачной ли является иерархия классов, при которой некоторый класс Х является производным от большого количества классов с большим числом полей в каждом ( AßB ß C ß…ß X)? Какая существует альтернатива наследованию?

3. Каким образом производится управление доступом к унаследованным компонентам производных классов? Есть ли в представленном фрагменте программы ошибки?

class Base {

int y;

public:

void setx(int n){x=n;}

void showx() const{ cout <<x<<endl;}

};

class Derived: public Base {

int x;

public:

void sety(int n){y=n;}

void show_sum() const{ cout<<x+y<<endl; }

void show() const {cout<<y<<endl; }

};

4. Есть ли ошибки в нижеследующих объявлениях:

Shape sh; // класс Shape абстрактный

Shape *psh;

Shape *psh1=new Shape();

 


Лабораторная работа 3. Виртуальные функции в С++



<== предыдущая лекция | следующая лекция ==>
Основные сведения | Виртуальные функции


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.122 сек.