Основы работы в С++

Тип работы:
Методичка
Предмет:
Программирование


Узнать стоимость

Детальная информация о работе

Выдержка из работы

Лабораторная работа 1

Тема: Создание классов и объект. Основные приемы работы с классами и объектами.

Задача 1

Разработать классы для описанных ниже объектов. Включить в класс методы set (…), get (…), show (…). Определить другие методы. Написать программу, демонстрирующую работу с этим классом. Класс соответствует индивидуальному варианту.

1. Student: Фамилия, Имя, Отчество, Дата рождения, Адрес, Средний балл, Факультет, Курс. Определить является ли студент «двоечником», «троечником», «хорошистом», «отличником».

#include< iostream>

using namespace std;

class student {

char fam[10];

char im[10];

char otch[10];

char datarog[10];

char adress[10];

double ball;

char fak[10];

char kurs[10];

public:

void set (char fam[10], char im[10], char otch[10], char datarog[10], char adress[10], double ball, char fak[10], char kurs[10])

{

strcpy (this-> fam, fam);

strcpy (this-> im, im);

strcpy (this-> otch, otch);

strcpy (this-> datarog, datarog);

strcpy (this-> adress, adress);

this-> ball=ball;

strcpy (this-> fak, fak);

strcpy (this-> kurs, kurs);

}

int get_rec (char f[10], char i[10], char o[10], char d[10], char ad[10], double & ba,

char faki[10], char ku[10])

{strcpy (f, fam);

strcpy (i, im);

strcpy (o, otch);

strcpy (d, datarog);

strcpy (ad, adress);

ba=ball;

strcpy (faki, fak);

strcpy (ku, kurs);

}

void show ()

{cout< < «informziyu"< <endl;

cout< <fam;

cout< <im<<endl;

cout< <otch<<endl;

cout< <datarog<<endl;

cout< <adress<<endl;

cout< <ball<<endl;

cout< <fak<<endl;

cout< <kurs<<endl;}

void red (double ball)

void red1 (double ball) {if ((ball> 4)||(ball<=5)) {cout< < «horoshist"< <endl;}

else {cout< < «troeishnik"< <endl;}}

void red3 (double ball) {if (ball==5) cout< < «otlichnik"< <endl;}

};

int main () {

student wee;

char a[10];

char b[10];

char c[10];

char d[10];

char q[10];

double w;

char e[10];

char t[10];

cout< < «vvedite dannie»;

cout< < «_____"< <endl;

cout< < «familiya"< <endl;

cin> >a;

cout< < «imya"< <endl;

cin> >b;

cout< < «otchestvo"< <endl;

cin> >c;

cout< < «datarog"< <endl;

cin> >d;

cout< < «adress"< <endl;

cin> >q;

cout< < «ball"< <endl;

cin> >w;

cout< < «fak"< <endl;

cin> >e;

cout< < «kurs"< <endl;

cin> >t;

wee. set (a, b, c, d, q, w, e, t);

wee. red (w);

wee. red1 (w);

wee. red3 (w);

wee. show ();

return 0;

}

Задание 2

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

2. Определить функции-члены класса для ввода и вывода членов-данных внутри объявления класса.

3. Составить программу, которая определяет четыре объекта класса и выводит их на экран. Первый объект должен инициализироваться по умолчанию, второй использовать конструктор инициализации, третий — преобразование типа своего параметра к типу своего класса, а четвертый — функцию ввода данных.

4. Выполнить программу и проверить соответствие заданных и полученных данных. 5. Определить функции ввода и вывода вне объявления класса и повторить выполнение программы.

6. Объявить функции ввода и вывода как «друзей» класса с параметром — объектом класса, передаваемым по значению. Изменить определение этих функций и повторить выполнение программы.

7. Объявить функции ввода и вывода как «друзей» класса с параметром — объектом класса, передаваемым по ссылке. Изменить определение этих функций и повторить выполнение программы.

#include< iostream>

using namespace std;

class comchislo

{

double x;

double y;

public:

comchislo (double x, double y)

{

this-> x=x;

this-> y=y;

}

void set (double x, double y)

{

this-> x=x;

this-> y=y;

}

void get1 (double & x, double & y)

{

this-> x=x;

this-> y=y;

}

void show ()

{

cout< < «z="< <x<< «+i*"< <y<<endl;

}

void set_s1 (double x, double y);

void get_s1 (double & x, double & y);

friend void vivod (comchislo o);

};

void comchislo: set_s1 (double x, double y)

{

this-> x=x;

this-> y=y;

}

void comchislo: get_s1 (double & x, double & y)

{

this-> x=x;

this-> y=y;

}

void vivod (double x, double y)

{

cout< < «z="< <x<< «+i*"< <y<<endl;

}

int main ()

{

double x, y;

comchislo o (0,0);

o. show ();

cout< < «Vvedite mnimoe i realnoe chislo"< <endl;

cin> >x>>y;

o. set (x, y);

o. show ();

o. set_s1 (x, y);

vivod (x, y);

return 0; }

Анология

#include< iostream>

using namespace std;

class comchislo

{

double x;

double y;

public:

comchislo (double x, double y)

{

this-> x=x;

this-> y=y;

}

void set (double x, double y)

{

this-> x=x;

this-> y=y;

}

void get1 (double & x, double & y)

{

this-> x=x;

this-> y=y;

}

double tim (double x, double y) {

return (x+y)/2−45; }

void show ()

{

cout< < «z="< <x<< «+i*"< <y<<endl;

}

};

int main ()

{

double k, z, p, p1;

double x, y;

comchislo o (0,0);

o. show ();

cout< < «Vvedite mnimoe i realnoe chislo"< <endl;

cin> >x>>y>>k>>z;

o. set (x, y);

p=o. tim (x, y) — o. tim (x, k)+2*o. tim (z, y);

cout< <p;

p1=o. tim (k, z) — o. tim (k, y)+o. tim (y, y) — o. tim (x, x);

cout< <p1;

x=p;

y=p1;

o. show ();

return 0;

}}

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

1) Что представляет собой класс?

Класс является описываемой на языке терминологии (пространства имён) исходного кода моделью ещё не существующей сущности (объекта). Фактически он описывает устройство объекта, являясь своего рода чертежом. Говорят, что объект — это экземпляр класса. При этом в некоторых исполняющих системах класс также может представляться некоторым объектом при выполнении программы посредством динамической идентификации типа данных. Обычно классы разрабатывают таким образом, чтобы их объекты соответствовали объектам предметной области.

2) Какие спецификации доступа используются при описании класса

В современных объектно-ориентированных языках программирования (в том числе в php, Java, C++, Oberon, Python, Ruby, Smalltalk, Object Pascal) создание класса сводится к написанию некоторой структуры, содержащей набор полей и методов (среди последних особую роль играют конструкторы, деструкторы, финализаторы). Практически класс может пониматься как некий шаблон, по которому создаются объекты — экземпляры данного класса. Все экземпляры одного класса созданы по одному шаблону, поэтому имеют один и тот же набор полей и методов.

private (закрытый, внутренний член класса) — обращения к члену допускаются только из методов того класса, в котором этот член определён. Любые наследники класса уже не смогут получить доступ к этому члену. Наследование по типу private запрещает доступ из дочернего класса ко всем членам родительского класса, включая даже public-члены (С++);

protected (защищённый, внутренний член иерархии классов) — обращения к члену допускаются из методов того класса, в котором этот член определён, а также из любых методов его классов-наследников. Наследование по типу protected делает все public-члены родительского класса protected-членами класса-наследника (С++);

public (открытый член класса) — обращения к члену допускаются из любого кода. Наследование по типу public не меняет модификаторов родительского класса (С++);

3) Что является элементами класса?

При использовании классов все элементы кода программы, такие как переменные, константы, методы, процедуры и функции, могут принадлежать (а во многих языках обязаны принадлежать) тому или иному классу. Сам класс в итоге определяется как список своих членов, а именно полей (свойств) и методов / функций / процедур. В зависимости от языка программирования к этому списку могут добавиться константы, атрибуты и внешние определения

4) Как осуществляется доступ к элементам класса

Принято объявлять в классах специальные методы — так называемые set и get функции, с помощью которых можно манипулировать элементами данных. set-функции инициализируют элементы данных, get-функции позволяют просмотреть значения элементов данных. Доработаем класс CppStudio так, чтобы в нём можно было хранить дату в формате дд. мм. гг. Для изменения и просмотра даты реализуем соответственно set и get функции.

5) Для чего используется указатель this

Указатель *this создается автоматически и указывает на объект, который вызывает метод

6) Что такое конструктор

В объектно-ориентированном программировании конструктор класса (от англ. constructor, иногда сокращают ctor) — специальный блок инструкций, вызываемый при создании объекта.

Конструктор схож с методом, но отличается от метода тем, что не имеет явным образом определённого типа возвращаемых данных, не наследуется, и обычно имеет различные правила для рассматриваемых модификаторов

7) Что такое деструктор

Деструмктор — специальный метод класса, служащий для деинициализации объекта (например освобождения памяти).

8) Какие классы и функции называются дружественными

В C++ существует возможность организации более гибкой защиты. Здесь можно также объявлять функции, отдельные функции-члены классов и даже классы (в этом случае речь идёт о полном множестве функций-членов класса), которые получают доступ к защищённым и приватным членам данного класса. Что означает реализацию системы управления доступом принципу «не допускать НИКОГО, КРОМЕ». Такие функции и классы называют дружественными функциями и классами

Лабораторная работа 2

Тема: Перегрузка функций и операторов

Создать класс целых чисел. Определить операторы «++» и «+», как методы класса, а" - - «и «-» как дружественные функции. Операторы должны позволять осуществления операций, как с переменными данного класса, так и с переменными встроенного целого.

#include< iostream>

using namespace std;

class zel

{

int f;

public:

zel () {f=0; }

zel (int f) {this-> f=f;}

int get_zel () {return f; }

void set_zel (int f) {this-> f=f;}

void show () {cout< < «F="< <f<<endl;}

int zel: operator ++(int a)

{

return a=a+a+a;

}

int zel: operator +(int a)

{

return a=a+3;

}

int zel: operator — (int a)

{int t;

t=a-a-a;

return t;

}

int zel: operator — (int a)

{

return a=a-5;

}

};

int main ()

{

zel a;

zel b;

int c;

cout< < «Vvedite a v formate"< <endl;

cin> >c;

int x;

cout< < «Vvedite b v"< <endl;

cin> >x;

a. set_zel (c);

b. set_zel (x);

a. show ();

b. show ();

c++;

cout< <c;

cout< <c+<<endl;

c -;

cout< <c;

cout< <c-<<endl;

system («pause»);

return 0;

}

«Комплексное число» — Complex. Класс должен содержать несколько конструкторов и операции для сложения, вычитания, умножения, деления, присваивания. Создать два вектора размерности n из комплексных координат. Передать их в функцию, которая выполняет сложение комплексных векторов.

#include < iostream. h>

#include < conio. h>

#include < math. h>

class Complex

{

private:

double real; // Действительная часть

double image; // Мнимая часть

public:

Complex () {}; // Конструктор по умолчанию

Complex (double r) {real = r; image = 0;} // Конструктор

Complex (double r, double i) {real = r, image = i;} // Конструктор

~Complex () {} // Деструктор

Complex operator+(Complex &); // Перегрузка оператора сложения

Complex operator — (Complex &); // Перегрузка оператора вычитания

Complex operator*(Complex &); // Перегрузка оператора умножения

Complex operator/(Complex &); // Перегрузка оператора деления

// Перегрузка функции-оператора < < для вывода класса Complex

friend ostream & operator<<(ostream &, Complex &);

// Перегрузка функции-оператора > > для ввода класса Complex

friend istream & operator>>(istream &, Complex &);

};

// Перегрузка +

Complex Complex: operator+(Complex & fp1)

{

fp1. real = real + fp1. real;

fp1. image = image + fp1. image;

return fp1;

}

// Перегрузка —

Complex Complex: operator — (Complex & fp1)

{

fp1. real = real — fp1. real;

fp1. image = image — fp1. image;

return fp1;

}

// Перегрузка *

Complex Complex: operator*(Complex & fp1)

{

double i, j;

i = real * fp1. real — image * fp1. image;

j = real * fp1. image + fp1. real * image;

fp1. real = i;

fp1. image = j;

return fp1;

}

// Перегрузка /

Complex Complex: operator/(Complex & fp1)

{

double k, i, j;

k = fp1. real * fp1. real + fp1. image * fp1. image;

i = (real * fp1. real + image * fp1. image) / k;

j = (fp1. real * image — real * fp1. image) / k;

fp1. real = i;

fp1. image = j;

return fp1;

}

// Перегрузка оператора < <

ostream & operator<< (ostream & fo, Complex & fp)

{

if (fp. image < 0) fo < < fp. real < < «+i („< < fp. image < <“)n»;

else fo < < fp. real < < «+i» < < fp. image < < «n»;

return fo;

}

// Перегрузка оператора > >

istream & operator>>(istream & fi, Complex & fp)

{

cout < < «vvedite deystvinui chasty: «;

fi > > fp. real;

cout < < «vvedite mnimui chasty: «;

fi > > fp. image;

return fi;

}

void main ()

{

//clrscr ();

// Комплексные числа

Complex c1, c2, c3, c4, c5;

// Ввод комплексных чисел

cin > > c1;

cin > > c2;

cin > > c3;

cin > > c4;

cin > > c5;

// Вывод комплексных чисел

cout < < «nc1 =» < < c1;

cout < < «c2 =» < < c2;

cout < < «c3 =» < < c3;

cout < < «c4 =» < < c4;

cout < < «c5 =» < < c5 < < 'n';

// cout < < «Модуль c1:» < < c1. abs () < < «nn»;

// Вывод результатов операций

Complex k;

K=c1+c2;

cout < < «c1 + c2 =» < < k;

k=c1-c2;

cout < < «c1 — c3 =» < < k;

k=c1*c2;

cout < < «c1 * c4 =» < < k;

k=c1/c2;

cout < < «c1 / c5 =» < < k;

getch (); }

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

1) Перегрузка оператора состоит в изменении смысла оператора (например, оператора плюс (+), который обычно в C++ используется для сложения) при использовании его с определенным классом

2) Чтобы разрешить существование нескольких одноимённых операций, достаточно ввести в язык правило, согласно которому операция (процедура, функция или оператор) опознаются компилятором не только по имени (обозначению), но и по типам их параметров. Таким образом, abs (i), где i объявлено как целое, и abs (x), где x объявлено как вещественное — это две разные операции. Принципиально в обеспечении именно такой трактовки нет никаких сложностей.

Чтобы дать возможность определять и переопределять операции, необходимо ввести в язык соответствующие синтаксические конструкции. Вариантов их может быть достаточно много, но по сути они ничем друг от друга не отличаются, достаточно помнить, что запись вида «< операнд1> < знакОперации> < операнд2>» принципиально аналогична вызову функции «< знакОперации>(<операнд1>,<операнд2>)». Достаточно разрешить программисту описывать поведение операторов в виде функций — и проблема описания решена.

3) Перегружать можно следующие операторы:

+ - * /% ^ & | ~! = < >

+= -= *= /=%= ^= &= |=

< < > > > >= < <= ==≠ <= > =

& & || ++ - -> *, -> [] ()

new new[] delete delete[]

А нельзя (подсмотрел у Страуструпа):

: (разрешение области видимости)

(выбор члена)

* (выбор члена через указатель на член)

?: тернарный оператор

sizeof, typeid

Лабораторная работа 3

Тема: Массивы объектов

Создать класс для работы со стеком. Элемент стека — действительное число. Применить класс для вывода возрастающих серий последовательности действительных чисел: a) в обратном порядке;

#include «stdafx. h»

#include «stdio. h»

#include «iostream»

using namespace std;

// элемент для стэка

struct elem {

int data;

struct elem* next;

};

// класс стэка

class lifo {

private:

struct elem* begin;

public:

// возвращает первый элемент из стека

struct elem* get () {

struct elem* rez;

if (begin≠NULL) {

rez=begin;

}

else {

rez=NULL;

}

return rez;

};

// поиск элемента

struct elem* search_elem (int idata) {

struct elem* curr;

curr=begin;

while ((curr-> data≠idata)&&(curr≠NULL)) {

curr=curr-> next;

};

return curr;

};

// функция создания

struct elem* create_lifo () {

struct elem* rez;

rez = new struct elem;

rez-> next=NULL;

return rez;

};

// функция добавления

void set (int data) {

struct elem* rez;

rez=create_lifo ();

rez-> data=data;

rez-> next=begin;

begin=rez;

};

// удаление элемента

void del1 () {

struct elem* temp;

temp=begin;

if (begin-> next≠NULL) {

begin=begin-> next;

}

else {

begin=NULL;

}

delete temp;

};

// удаление целевого элемента

void del2 (int idata) {

struct elem* curr;

struct elem* temp;

curr=begin;

temp=search_elem (idata);

while ((curr-> next≠temp)&&(curr->next≠NULL)) {

curr=curr-> next;

};

curr-> next=temp->next;

if (temp==begin) {

begin=begin-> next;

}

delete temp;

};

// просмотр стeкa

void write_lifo () {

struct elem* curr;

curr=begin;

cout < < «NACHALO» < < endl;

while (curr≠NULL) {

cout < < curr-> data < < endl;

curr = curr-> next;

}

cout < < «KONEC» < < endl;

};

// сортировка

struct elem* find_max (struct elem* curr) {

struct elem* max=curr;

do {

if (curr-> data>max->data) {

max=curr;

}

curr=curr-> next;

} while (curr≠NULL);

return max;

};

void sort_lifo () {

struct elem *max, *curr, *temp, *ntemp;

curr=begin;

do {

max=find_max (curr);

if (max≠curr) {

temp=curr;

if (max≠begin) {

while ((temp-> next≠max)&&(temp->next≠NULL)) {

temp=temp-> next;

}; };

temp-> next=max->next; // убрали мах из стека

temp=begin;

while ((temp-> next≠curr)&&(temp->next≠NULL)) {

temp=temp-> next;

};

if (temp-> next≠NULL) {

temp-> next=max;

max-> next=curr;

} else

{

max-> next=curr;

begin=max;

}

// нашли и сменили элемент

curr=max;

}

curr=curr-> next;

} while (curr-> next≠NULL);

};

} mlifo;

// создаем стек

void c_lifo () {

int i=0, t;

mlifo. create_lifo ();

do {

cout < < «vvedite» < < i < < «element (0-vyhod)» < <endl;

cin > > t;

i++;

mlifo. set (t);

} while (t≠0);

};

void add_elem () {

int t;

cout < < «vvedite element» < <endl;

cin > > t;

mlifo. set (t);

}

void del_elem () {

int t;

cout < < «vvedite chislo dlya udaleniya» < <endl;

cin > > t;

mlifo. del2 (t);

};

int main ()

{

int i;

bool flag=true;

do {

_flushall ();

cout < < «sozdat stek (1)» < < endl;

cout < < «dobavit element (2)» < < endl;

cout < < «udalit s vershiny (3)» < < endl;

cout < < «pokazat stek (4)» < < endl;

cout < < «udalit celevoi element (5)» < < endl;

cout < < «sortirovka (6)» < < endl;

cout < < «vyhod (0)» < < endl;

cin > >i;

switch (i) {

case 1: c_lifo (); break;

case 2: add_elem (); break;

case 3: mlifo. del1 (); break;

case 4: mlifo. write_lifo (); break;

case 5: del_elem (); break;

case 6: mlifo. sort_lifo (); break;

case 0: flag=false; break;

};

} while (flag);

return 0;

}

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

1) C++ ссылка — это простой ссылочный тип, менее мощный, но более безопасный, чем указатель, унаследованый от языка Си.

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

2) new — оператор, обеспечивающий выделение динамической памяти в куче. За исключением формы, называемой «размещающей формой new», new пытается выделить достаточно памяти в куче для размещения новых данных и, в случае успеха, возвращает адрес свежевыделенной памяти. Однако, если new не может выделить память в куче, то он передаст (throw) исключение типа std: bad_alloc. Это устраняет необходимость явной проверки результата выделения.

p_var = new typename;

3) В языке программирования C++ оператор delete возвращает память, выделенную оператором new, обратно в кучу. Вызов delete должен происходить для каждого вызова new, дабы избежать утечки памяти. После вызова delete объект, указывающий на этот участок памяти, становится некорректным и не должен больше использоваться. Многие программисты присваивают 0 (нуль-указатель) указателям после использования delete, чтобы минимизировать количество ошибок программирования. Однако нужно отметить, что удаление нуль-указателя фактически не имеет эффекта, так что нет необходимости проверять нуль-указатель перед вызовом delete

int *p_var = NULL; // объявление нового указателя

p_var = new int; // память динамически выделяется

/*…

остальной код

delete p_var; // память освобождается

p_var = NULL; // указатель заменяется на 0 (нуль-указатель)

Лабораторная работа 4

Тема: Реализация одиночного наследования

Цели работы:

? изучение наследования, преимущества и недостатки;

? изучение композиции;

? изучение правил определения наследования и композиции;

? изучение форм наследования;

? изучение инициализаторов;

? принцип подстановки;

? наследование и композиция — что выбрать.

Задача

а) Создать иерархию классов игра — спортивная игра — волейбол. Определить конструкторы, деструктор, оператор присваивания и другие необходимые функции. Продемонстрировать работу классов.

#include < iostream>

#include < string. h>

using namespace std;

class igra

{

public:

int kol_igrokof;

igra (char *vid_igri, char *atributi, int kol_igrokof, char *vremya_igri) {

strcpy (igra: vid_igri, vid_igri);

strcpy (igra: atributi, atributi);

this-> kol_igrokof=kol_igrokof;

strcpy (igra: vremya_igri, vremya_igri); };

void show_spisok (void) {cout < < vid_igri < < endl;

cout< <atributi<<endl;

cout< <vremya_igri<<endl;};

void show_kol (int) {cout < < kol_igrokof < < endl; };

char vid_igri[64];

char atributi[64];

char vremya_igri[64];

};

class sport_play: public igra

{

public:

sport_play (char *vid_igri, char *vremya_igri, char *tematika, int kol_igrokof, char*atributi): igra (vid_igri, atributi, kol_igrokof, vremya_igri)

{

strcpy (this-> vremya_igri, vremya_igri);

strcpy (this-> tematika, tematika);

strcpy (this-> atributi, atributi);

this-> kol_igrokof=kol_igrokof;

};

void show_sport_play (void)

{

cout < < «vid igri: «;

show_spisok ();

cout< <endl;

cout < <"tematika: «< <tematika;

cout< < «kol =»;

cout< <endl;

show_kol (kol_igrokof);

cout < <endl;

};

private:

char tematika[64];

};

class volebol: public igra

{

public:

volebol (char *vid_igri, char *vremya_igri, char *kol_match, int kol_igrokof, char*atributi): igra (vid_igri, atributi, kol_igrokof, vremya_igri)

{

strcpy (volebol: vremya_igri, vremya_igri);

strcpy (volebol: kol_match, kol_match);

strcpy (volebol: atributi, atributi);

this-> kol_igrokof=kol_igrokof;

};

void show_volebol (void)

{

cout < < «nazvanie: «;

show_spisok ();

cout< <endl;

cout < <"kolmatch: «< < kol_match;

cout< < «Kol =»;

cout< <endl;

show_kol (kol_igrokof);

cout < <endl;

};

private:

char kol_match[64];

};

int main (void)

{

char vid_igri[64];

char vremya_igri[64];

char kol_match[54];

char atributi[64];

char tematika[64];

int kol_igrokof;

cout< < «vid igri"< <endl;

cin> >vid_igri;

cout< < «_________________»;

cout< < «vremya"< <endl;

cin> >vremya_igri;

cout< < «_________________»;

cout< < «kolmatch"< <endl;

cin> >kol_match;

cout< < «_________________»;

cout< < «atributi"< <endl;

cin> >atributi;

cout< < «__________________»;

cout< < «tematika"< <endl;

cin> >tematika;

cout< < «__________________»;

cout< < «kol igrokof"< <endl;

cin> >kol_igrokof;

cout< < «__________________»;

igra o (vid_igri, atributi, kol_igrokof, vremya_igri);

cout< < «SPISOK"< <endl;

o. show_spisok ();

sport_play as (vid_igri, vremya_igri, tematika, kol_igrokof, atributi);

cout< < «____________________Igra"< <endl;

as. show_sport_play ();

volebol das (vid_igri, vremya_igri, kol_match, kol_igrokof, atributi);

cout< < «__________________VOLEBOL"< <endl;

das. show_volebol ();

system («pause»);

return 0;

}

b) Создать класс колесо, имеющий радиус. Определить конструкторы и методы доступа. Создать класс автомобиль, имеющий колеса и строку обозначающую фирму-производителя. Создать производный класс грузовой автомобиль, отличающийся грузоподъемностью. Определить конструкторы, деструктор и другие необходимые функции. Продемонстрировать работу классов.

#include < iostream>

#include < string. h>

using namespace std;

class koleso

{

public:

double rad;

koleso (double rad) {

this-> rad=rad;

}

void set_rad (double rad)

{this-> rad=rad;}

void show_rad (void) {

cout < <"radius__=__>"<<rad<< endl;

};

};

class afto: public koleso

{

public:

char spisok[20];

afto (char*spisok, double rad): koleso (rad)

{

this-> rad=rad;

strcpy (this-> spisok, spisok);

}

void set_iz1 ()

{

this-> rad=rad;

strcpy (this-> spisok, spisok);

}

void show_ss (void)

{

cout < <"radius__=__>"<<rad<< endl;

cout< <"firma proizvoditelya__=__> «<<spisok<<endl;

};

};

class gruzavto: public afto {

public:

double pod;

gruzavto (double rad, char*spisok, double pod): afto (spisok, rad)

{

this-> pod=pod;

this-> rad=rad;

strcpy (this-> spisok, spisok);

}

void set_ss () {this-> rad=rad;

strcpy (this-> spisok, spisok);

this-> pod=pod;}

void show_ss3 (void)

{

cout < <"radius____=___>"<<rad<< endl;

cout< <"firma proizvoditelya__=___> «<<spisok<<endl;

cout< <"podem___=__>"<<pod<<endl;

};

};

int main (void)

{bool t=false;

double pod;

cout< < «podem"< <endl;

cin> >pod;

double rad;

cout< < «radius"< <endl;

cin> >rad;

char spisok[20];

cout< < «spisok proizvoditelya"< <endl;

cin> >spisok;

koleso a (rad);

while (t=true)

{int d;

cout< < «vesti novi radius??? da=1 net=2"< <endl;

cin> >d;

if (d==1) {

cout< < «vvedite radius"< <endl;

cin> >rad;

a. set_rad (rad);

a. show_rad ();}

else {

break; }

}

cout< < «________________koleso"< <endl;

a. show_rad ();

afto a1 (spisok, rad);

cout< < «________________avto"< <endl;

a1. show_ss ();

while (t=true) {

int d;

cout< <"vvesti noviq spisok??? da=1, net=2; «< <endl;

cin> >d;

if (d==1) {

cout< < «vvedite noviy spisok"< <endl;

cin> >spisok;

afto a1 (spisok, rad);

a1. show_ss ();}

else {

break; }

}

gruzavto a2 (rad, spisok, pod);

cout< < «____gruzovoeavto"< <endl;

a2. show_ss3 ();

while (t=true)

{int d;

cout< <"vvestinoviy podem??? da=1, net=2; «< <endl;

cin> >d;

if (d==1) {cout< < «vvedite noviy podyem"< <endl;

cin> >pod;

gruzavto a2 (rad, spisok, pod);

a2. show_ss3 ();

}

else {

break; }}

cout< < «________________gruzovik"< <endl;

a2. show_ss3 ();

system («pause»);

return 0;

}

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

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

Простое наследование

Класс, от которого произошло наследование, называется базовым или родительским (англ. base class). Классы, которые произошли от базового, называются потомками, наследниками или производными классами (англ. derived class).

Множественное наследование

При множественном наследовании у класса может быть более одного предка. В этом случае класс наследует методы всех предков. Достоинства такого подхода в большей гибкости. Множественное наследование реализовано в C++. Из других языков, предоставляющих эту возможность, можно отметить Python и Эйфель. Множественное наследование поддерживается в языке UML.

2) Композиция включает в себя несколько весьма важных составляющих, которые и определяют, насколько легко будет работать с приложением. Композиция в программировании включает в себя расположение управляющих элементов, эффективное использование свободного пространства и «позволительность»

3) Использование наследования для построения новых классов сэкономит вам значительное время и силы на программирование. Объектно-ориентированное программирование широко использует наследование, позволяя вашей программе строить сложные объекты из небольших легко управляемых объектов.

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

5) Принцип подстановки утверждает, что если есть два класса, А и В такие, что класс В является подклассом класса, А (возможно, отстоя в иерархии на несколько ступеней), то мы должны иметь возможность подставить представителя класса В вместо представителя класса, А в любой ситуации, причем без видимого эффекта.

6) Самый большой недостаток наследования заключается в том, что оно легко нарушает один из базовых принципов ООП — инкапсуляцию. Это связано с тем, что фактически родительский класс определяет поведение дочернего класса, а это значит, что даже незначительное изменение в родительском классе может сильно сказаться на поведении класса-потомка. Плюс ко всему, повторное использование кода сильно затрудняется, если реализация родителя содержит аспекты несовместимые с задачами потомка. Как правило, чтобы выйти из такой ситуации необходимо провести глубокий рефакторинг кода, а это не всегда возможно.

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

Лабораторная работа 5

Тема: Множественное наследование

Цели работы:

? изучение правил определения множественного наследования;

? изучение преимуществ и недостатков множественного наследования;

? проблем связанных с использованием множественного наследования;

? изучение решений проблем;

1) Создать иерархии наследования: студент, сотрудник — практикант.

#include< iostream>

using namespace std;

class Student {

int mark;

char imya[20];

char fam[20];

public:

void Set_student (int mark, char *imya, char*fam)

{strcpy (this-> imya, imya);

strcpy (this-> fam, fam);

this-> mark=mark;

}

void show1 () {

cout< < «__"< < «="< <mark<<endl;

cout< < «__"< < «Imya="< <imya<<endl;

cout< < «__"< < «familiya="< <fam<<endl;};

};

class Worker {

int salary;

double stag;

public:

void Set_Worker (int salary, double stag) {

this-> salary=salary;

this-> stag=stag;

}

void show2 () {

cout< < «__"< < «zarplata="< <salary<<endl;

cout< < «__"< < «stag="< <stag<<endl;}

};

class Practicant: public Student, public Worker

{char srok[20];

int ozenka;

public:

void set_practicant (char*srok, int ozenka)

{strcpy (this-> srok, srok);

this-> ozenka=ozenka;

}

void show3 () {

cout< < «__"< < «srok="< <srok<<endl;

cout< < «__"< < «ozenk="< <ozenka<<endl;

}

};

int main () {

Practicant s, w;

s. Set_student (1222, «Kolya», «kinim»);

s. show1 ();

s. set_practicant («11juli», 12);

s. show3 ();

cout< < «___"< <endl;

w. Set_Worker (12 333,13);

w. show2 ();

w. set_practicant («11avg», 12);

w. show3 ();

return 0;

}

2) Создать иерархии наследования: человек — студент, сотрудник — практикант.

#include < iostream>

#include < string. h>

using namespace std;

class chel

{

public:

char pol[20];

chel (char *pol) {

strcpy (this-> pol, pol);

}

void set_pol (char*pol)

{strcpy (this-> pol, pol); }

void show_pol (void) {

cout < <"pol__=__>"<<pol<< endl;

};

};

class student: public chel

{

public:

double stip;

char imya[20];

student (char*imya, double stip, char*pol): chel (pol)

{

strcpy (this-> pol, pol);

strcpy (this-> imya, imya);

this-> stip=stip;

}

void set_iz1 ()

{

this-> stip=stip;

strcpy (this-> pol, pol);

strcpy (this-> imya, imya);

}

void show01 (void)

{

cout < <"stip__=__>"<<stip<< endl;

cout< <"pol__=__>"<<pol<<endl;

cout< <"imya__=__>"<<imya<<endl;

};

};

class worck: public chel {

public:

double zarp;

char stag[20];

worck (char*stag, double zarp, char*pol): chel (pol)

{

strcpy (this-> pol, pol);

strcpy (this-> stag, stag);

this-> zarp=zarp;

}

void set_z2 ()

{

this-> zarp=zarp;

strcpy (this-> pol, pol);

strcpy (this-> stag, stag);

}

void show02 (void)

{

cout < <"zarp__=__>"<<zarp<< endl;

cout< <"pol__=__>"<<pol<<endl;

cout< <"stag__=__>"<<stag<<endl;

};

};

class pract: public worck {

public:

double ozen;

char srok[20];

pract (double ozen, char*srok, char*stag, double zarp, char*pol): worck (stag, zarp, pol)

{strcpy (this-> pol, pol);

strcpy (this-> stag, stag);

this-> zarp=zarp;

this-> ozen=ozen;

strcpy (this-> srok, srok);

}

void set_ss () {this-> ozen=ozen;

strcpy (this-> srok, srok);

strcpy (this-> stag, stag);

this-> zarp=zarp;

strcpy (this-> pol, pol); }

void show_ss3 (void)

{

cout < <"ozenka____=___>"<<ozen<< endl;

cout< <"srok sdachi__=___> «<<srok<<endl;

cout< <"stag__=__>"<<stag<<endl;

cout< <"zarplata__=__>"<<zarp<<endl;

cout< <"pol__=__>"<<pol<<endl;

};

};

int main (void)

{

double stip;

cout< < «stip"< <endl;

cin> >stip;

double zarp;

cout< < «zarplata"< <endl;

cin> >zarp;

char pol[20];

cout< < «pol"< <endl;

cin> >pol;

char imya[20];

cout< < «vvedite imya"< <endl;

cin> >imya;

char stag[20];

cout< < «vvediter stag"< <endl;

cin> >stag;

double ozen;

cout< < «vvedit ozenku"< <endl;

cin> >ozen;

char srok[20];

cout< < «vvedite srok"< <endl;

cin> >srok;

chel a (pol);

cout< < «________________chel"< <endl;

a. show_pol ();

student a1 (imya, stip, pol);

cout< < «________________student"< <endl;

a1. show01 ();

worck a3 (stag, zarp, pol);

cout< < «________________worck"< <endl;

a3. show02 ();

pract a2 (ozen, srok, stag, zarp, pol);

cout< < «_________________pract"< <endl;

a2. show_ss3 ();

system («pause»);

return 0;

}

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

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

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

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

2)

3) семантическая неопределенность часто совокупно представляется как Проблема ромба

отсутствует возможность явного многократного наследования от одного класса

порядок наследования изменяет семантику класса

Перекрытие имен функций — эта проблема есть как и в обычном наследовании, так и в множественном.

Перекрытие виртуальных функцій

Представление объекта в памяти

4) Виртуамльное наслемдование (англ. virtual inheritance) в языке программирования C++ - один из вариантов наследования, который нужен для решения некоторых проблем, порождаемых наличием возможности множественного наследования (особенно «ромбовидного наследования»), путем разрешения неоднозначности того, методы которого из суперклассов (непосредственных классов-предков) необходимо использовать. Оно применяется в тех случаях, когда множественное наследование вместо предполагаемой полной композиции свойств классов-предков приводит к ограничению доступных наследуемых свойств вследствие неоднозначности. Базовый класс, наследуемый множественно, определяется виртуальным с помощью ключевого слова virtual.

5) Виртуальное наследование не является явной характеристикой самого базового класса, а лишь описывает его отношение к производному. Как мы уже отмечали, виртуальное наследование — это разновидность композиции по ссылке. Иначе говоря, доступ к подобъекту и его нестатическим членам косвенный, что обеспечивает гибкость, необходимую для объединения нескольких виртуально унаследованных подобъектов базовых классов в один разделяемый экземпляр внутри производного. В то же время объектом производного класса можно манипулировать через указатель или ссылку на тип базового, хотя последний является виртуальным

Лабораторная работа 6

Тема: Виртуальные функции

Цели работы:

? исследование полиморфизма;

? изучение принципов позднего связывания;

? изучение виртуальных функций;

? полиморфизм ad-hoc;

? реализация виртуальных функций;

? изучение абстрактных классов.

Задания

Вариант 1

Создать абстрактный базовый класс Worker с виртуальной функцией начисления зарплаты. Создать производные классы StateWorker, HourlyWorker и CommissionWorker, в которых данная функция переопределена.

#include< iostream>

using namespace std;

class worker {

public:

double i;

worker (double x) {i=x; }

virtual void func () {cout< < «zarplata standartnogo rabochego"< <endl;

cout< <i;}

};

class stateworker: public worker {

public:

stateworker (double x): worker (x){}

void func () {cout< < «zarplata stateworker"< <endl;

cout< <i*1. 5<<endl;}};

class horlyworker: public worker {

public:

horlyworker (double x): worker (x){}

void func () {

cout< < «zarplata horlyworker»;

cout< <i*2<<endl;

}};

class communicationworker: public worker {

public:

communicationworker (double x): worker (x){}

void func () {cout< < «zarplata communicationworker"< <endl;

cout< <i*2. 5<<endl;}};

int main () {

worker *p;

worker ob (1000);

stateworker d_ob1 (1000);

horlyworker d_ob2 (1000);

communicationworker d_ob3 (1000);

p=& ob;

p-> func ();

p=& d_ob1;

p-> func ();

p=& d_ob2;

p-> func ();

p=& d_ob3;

p-> func ();

return 0;

}

класс шаблон виртуальный оператор

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

1) В общем случае полиморфизм представляет собой способность объекта изменять форму. Если вы разделите этот термин на части, то обнаружите, что поли означает много, а морфизм относится к изменению формы. Полиморфный объект, следовательно, представляет собой объект, который может принимать разные формы. Этот урок вводит понятие полиморфизма и рассматривает, как использовать полиморфные объекты внутри ваших программ для упрощения и уменьшения кода. К концу данного урока вы освоите следующие основные концепции:

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

C++ упрощает создание полиморфных объектов.

Для создания полиморфных объектов ваши программы должны использовать виртуальные (virtual) функции.

Виртуальная (virtual) функция — это функция базового класса, перед именем которой стоит ключевое слово virtual.

Любой производный от базового класс может использовать или перегружать виртуальные функции.

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

2) Виртуальный метод (виртуальная функция) — в объектно-ориентированном программировании метод (функция) класса, который может быть переопределён в классах-наследниках так, что конкретная реализация метода для вызова будет определяться во время исполнения. Таким образом, программисту необязательно знать точный тип объекта для работы с ним через виртуальные методы: достаточно лишь знать, что объект принадлежит классу или наследнику класса, в котором метод объявлен.

Переопределение метода (англ. Method overriding) в объектно-ориентированном программировании — одна из возможностей языка программирования, позволяющая подклассу или дочернему классу обеспечивать специфическую реализацию метода, уже реализованного в одном из суперклассов или родительских классов. Реализация метода в подклассе переопределяет (заменяет) его реализацию в суперклассе, описывая метод с тем же названием, что и у метода суперкласса, а также у нового метода подкласса должны быть те же параметры или сигнатура, тип возвращаемого результата, что и у метода родительского класса

4) При позднем связывании адреса определяются динамически во время выполнения программы, а не статически во время компиляции, как в традиционных компилируемых языках, в которых применяется раннее связывание. Сам процесс связывания заключается в замене виртуальных функций на адреса памяти.

ПоказатьСвернуть
Заполнить форму текущей работой