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

  • Вид работы:
    Методичка
  • Предмет:
    Информационное обеспечение, программирование
  • Язык:
    Русский
    ,
    Формат файла:
    MS Word
    678,59 Кб
  • Опубликовано:
    2012-04-15
Вы можете узнать стоимость помощи в написании студенческой работы.
Помощь в написании работы, которую точно примут!

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

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

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

Задача 1

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

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

#include<iostream>

using namespace std;student {fam[10];im[10];otch[10];datarog[10];adress[10];ball;fak[10];kurs[10];:set (char fam[10], char im[10], char otch[10], char datarog[10], char adress[10], double ball, char fak[10], char kurs[10])

{(this->fam, fam);(this->im, im);(this->otch, otch);(this->datarog, datarog);(this->adress, adress);>ball=ball;(this->fak, fak);(this->kurs, kurs);

}get_rec (char f[10], char i[10], char o[10], char d[10], char ad[10], double & ba,faki[10], char ku[10])

{strcpy (f, fam);(i, im);(o, otch);(d, datarog);(ad, adress);=ball;(faki, fak);(ku, kurs);

}show()               

{cout<< «informziyu»<<endl;<<fam;<<im<<endl;<<otch<<endl;<<datarog<<endl;<<adress<<endl;<<ball<<endl;<<fak<<endl;<<kurs<<endl;}red (double ball) {if ((ball>0)||(ball<3)) cout<< «dvoichick»<<endl;}red1 (double ball) {if ((ball>4)||(ball<=5)) {cout<< «horoshist»<<endl;}{cout<< «troeishnik»<<endl;}}red3 (double ball) {if (ball==5) cout<< «otlichnik»<<endl;}

};main() {

         student wee;a[10];b[10];c[10];d[10];q[10];w;e[10];t[10];<< «vvedite dannie»;<< "_____"<<endl;<< «familiya»<<endl;>>a;<< «imya»<<endl;>>b;<< «otchestvo»<<endl;>>c;<< «datarog»<<endl;>>d;<< «adress»<<endl;>>q;<< «ball»<<endl;>>w;<< «fak»<<endl;>>e;<< «kurs»<<endl;>>t;.set (a, b, c, d, q, w, e, t);.red(w);.red1 (w);.red3 (w);.show();

return 0;

}

Задание 2

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

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

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

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

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

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

#include<iostream>namespace std;comchislo

{

double x;y;

:(double x, double y)

{>x=x;>y=y;

}set (double x, double y)

{>x=x;>y=y;

}get_1 (double &x, double &y)

{>x=x;>y=y;

}show()

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

}set_s1 (double x, double y);get_s1 (double &x, double &y);

friend void vivod (comchislo o);

};comchislo:set_s1 (double x, double y)

{>x=x;>y=y;

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

{>x=x;>y=y;

}vivod (double x, double y)

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

}main()

{x, y;o (0,0);.show();<< «Vvedite mnimoe i realnoe chislo»<<endl;>>x>>y;.set (x, y);.show();.set_s1 (x, y);(x, y);0;}

Анология

#include<iostream>  

using namespace std;comchislo

{x;y;:(double x, double y)

{>x=x;>y=y;

}set (double x, double y)

{>x=x;>y=y;

}get_1 (double &x, double &y)

{>x=x;>y=y;

}tim (double x, double y) {(x+y)/2-45;}show()

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

}

};main()

{k, z, p, p1;x, y;o (0,0);.show();<< «Vvedite mnimoe i realnoe chislo»<<endl;>>x>>y>>k>>z;.set (x, y);=o.tim (x, y) - o.tim (x, k)+2*o.tim (z, y);<<p;=o.tim (k, z) - o.tim (k, y)+o.tim (y, y) - o.tim (x, x);<<p1;=p;=p1;.show();0;

}}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#include<iostream>namespace std;zel

{f;:() {f=0;}(int f) {this->f=f;}get_zel() {return f;}set_zel (int f) {this->f=f;}show() {cout<< «F=»<<f<<endl;}zel:operator ++(int a)

{a=a+a+a;

}zel:operator +(int a)

{a=a+3;

}zel:operator - (int a)

{int t;

=a-a-a;t;

}zel:operator - (int a)

{a=a-5;

}

};main()

{a;b;c;<< «Vvedite a v formate»<<endl;>>c;x;<< «Vvedite b v»<<endl;>>x;.set_zel(c);.set_zel(x);.show();.show();

++;<<c;<<c+<<endl;-;<<c;<<c-<<endl;(«pause»);

return 0;

}

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

#include <iostream.h>

#include <conio.h>

#include <math.h>Complex

{:real; // Действительная частьimage; // Мнимая часть:() {}; // Конструктор по умолчанию(double r) {real = r; image = 0;} // Конструктор(double r, double i) {real = r, image = i;} // Конструктор

~Complex() {} // Деструкторoperator+(Complex &); // Перегрузка оператора сложенияoperator - (Complex &); // Перегрузка оператора вычитанияoperator*(Complex &); // Перегрузка оператора умножения operator/(Complex &); // Перегрузка оператора деления

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

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

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

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

};

// Перегрузка +Complex:operator+(Complex &fp1)

{.real = real + fp1.real;.image = image + fp1.image;fp1;

}

// Перегрузка -Complex:operator - (Complex &fp1)

{.real = real - fp1.real;.image = image - fp1.image;fp1;

}

// Перегрузка *Complex:operator*(Complex &fp1)

{i, j;= real * fp1.real - image * fp1.image;= real * fp1.image + fp1.real * image;.real = i;.image = j;fp1;

}

// Перегрузка /Complex:operator/(Complex &fp1)

{k, i, j;= fp1.real * fp1.real + fp1.image * fp1.image;= (real * fp1.real + image * fp1.image) / k;= (fp1.real * image - real * fp1.image) / k;.real = i;.image = j;fp1;

}

// Перегрузка оператора <<&operator<< (ostream &fo, Complex &fp)

{(fp.image < 0) fo << fp.real << «+i (» << fp.image <<»)\n»;fo << fp.real << «+i» << fp.image << «\n»;fo;

}

// Перегрузка оператора >>&operator>>(istream &fi, Complex &fp)

{<< «vvedite deystvinui chasty:»;>> fp.real;<< «vvedite mnimui chasty:»;>> fp.image;fi;

}main()

{

//clrscr();

// Комплексные числаc1, c2, c3, c4, c5;

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

cin >> c2;>> c3;>> c4;

cin >> c5;

// Вывод комплексных чисел<< «\nc1 =» << c1;

cout << «c2 =» << c2;<< «c3 =» << c3;<< «c4 =» << c4;<< «c5 =» << c5 << '\n';

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

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

K=c1+c2;<< «c1 + c2 =» << k;=c1-c2;<< «c1 - c3 =» << k;=c1*c2;<< «c1 * c4 =» << k;=c1/c2;<< «c1 / c5 =» << k;();}

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

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

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

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

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

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

<< >> >>= <<= ==!= <= >=

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

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

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

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

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

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

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

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

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

#include «stdafx.h»      

#include «stdio.h»

#include «iostream»namespace std;

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

struct elem {

int data;elem* next;

};

// класс стэкаlifo {: elem* begin;

public:

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

struct elem* get() {elem* rez;(begin!=NULL) {=begin;

}{=NULL;

}rez;

};

// поиск элементаelem* search_elem (int idata) {elem* curr;=begin;((curr->data!=idata)&&(curr!=NULL)) {=curr->next;

};curr;

};

// функция созданияelem* create_lifo() {elem* rez;= new struct elem;>next=NULL;rez;

};

// функция добавленияset (int data) {elem* rez;=create_lifo();>data=data;>next=begin;=rez;

};

// удаление элементаdel_1 () {elem* temp;=begin;(begin->next!=NULL) {=begin->next;

}{=NULL;

}temp;

};

// удаление целевого элементаdel_2 (int idata) {elem* curr;elem* temp;=begin;=search_elem(idata);((curr->next!=temp)&&(curr->next!=NULL)) {=curr->next;

};>next=temp->next;(temp==begin) {=begin->next;

}temp;

};

// просмотр стeкawrite_lifo() {elem* curr;=begin;<< «NACHALO» << endl;(curr!=NULL) {<< curr->data << endl;= curr->next;

}<< «KONEC» << endl;

};

// сортировкаelem* find_max (struct elem* curr) {elem* max=curr;{(curr->data>max->data) {=curr;

}=curr->next;

} while (curr!=NULL);max;

};sort_lifo() {elem *max, *curr, *temp, *ntemp;=begin;{=find_max(curr);(max!=curr) {=curr;(max!=begin) {((temp->next!=max)&&(temp->next!=NULL)) {=temp->next;

};};>next=max->next; // убрали мах из стека=begin;((temp->next!=curr)&&(temp->next!=NULL)) {=temp->next;

};(temp->next!=NULL) {>next=max;>next=curr;

} else

{>next=curr;=max;

}

// нашли и сменили элемент=max;

}=curr->next;

} while (curr->next!=NULL);

};

} mlifo;

// создаем стекc_lifo() {i=0, t;.create_lifo();{<< «vvedite» << i << «element (0-vyhod)» <<endl;>> t;++;.set(t);

} while (t!=0);

};add_elem() {t;<< «vvedite element» <<endl;>> t;.set(t);

}del_elem() {t;<< «vvedite chislo dlya udaleniya» <<endl;>> t;.del_2 (t);

};main()

{i;flag=true;{

_flushall();<< «sozdat stek(1)» << endl;<< «dobavit element(2)» << endl;<< «udalit s vershiny(3)» << endl;<< «pokazat stek(4)» << endl;<< «udalit celevoi element(5)» << endl;<< «sortirovka(6)» << endl;<< «vyhod(0)» << endl;>>i;(i) {1: c_lifo(); break;2: add_elem(); break;3: mlifo.del_1 (); break;4: mlifo.write_lifo(); break;5: del_elem(); break;6: mlifo.sort_lifo(); break;0: flag=false; break;

} while(flag); 0;

}

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

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

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

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

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

/*…….

остальной кодp_var; // память освобождается_var = NULL; // указатель заменяется на 0 (нуль-указатель)

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

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

Цели работы:

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

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

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

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

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

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

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

Задача

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

#include <iostream>

#include <string.h>namespace std;igra

{:kol_igrokof;(char *vid_igri, char *atributi, int kol_igrokof, char *vremya_igri) {(igra:vid_igri, vid_igri);(igra:atributi, atributi);>kol_igrokof=kol_igrokof;(igra:vremya_igri, vremya_igri);};

show_spisok(void) {cout << vid_igri << endl;<<atributi<<endl;<<vremya_igri<<endl;};

show_kol(int) {cout << kol_igrokof << endl;};vid_igri[64];atributi[64];vremya_igri[64];

};

sport_play: public igra

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

{(this->vremya_igri, vremya_igri);

strcpy (this->tematika, tematika);(this->atributi, atributi);>kol_igrokof=kol_igrokof;

};show_sport_play(void)

{<< «vid igri:»;_spisok();<<endl;<<«tematika: «<<tematika;<< «kol =»;<<endl;_kol (kol_igrokof);

cout <<endl;

};:

tematika[64];

};

volebol: public igra

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

{(volebol:vremya_igri, vremya_igri);(volebol:kol_match, kol_match);(volebol:atributi, atributi);>kol_igrokof=kol_igrokof;

};show_volebol(void)

{<< «nazvanie:»;_spisok();<<endl;<<«kolmatch: «<< kol_match;<< «Kol =»;<<endl;_kol (kol_igrokof);<<endl;

};:kol_match[64];

};main(void)

{vid_igri[64];vremya_igri[64];kol_match[54];atributi[64];tematika[64];kol_igrokof;<< «vid igri»<<endl;>>vid_igri;<< "_________________»;<< «vremya»<<endl;>>vremya_igri;<< "_________________»;<< «kolmatch»<<endl;>>kol_match;<< "_________________»;<< «atributi»<<endl;>>atributi;<< "__________________»;<< «tematika»<<endl;>>tematika;<< "__________________»;<< «kol igrokof»<<endl;>>kol_igrokof;<< "__________________»;o (vid_igri, atributi, kol_igrokof, vremya_igri);<< «SPISOK»<<endl;.show_spisok();_play as (vid_igri, vremya_igri, tematika, kol_igrokof, atributi);<< "____________________Igra»<<endl;.show_sport_play();das (vid_igri, vremya_igri, kol_match, kol_igrokof, atributi);<< "__________________VOLEBOL»<<endl;.show_volebol();

system («pause»);0;

}

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


#include <iostream>                

#include <string.h>namespace std;koleso

{:rad;(double rad) {>rad=rad;

}set_rad (double rad)

{this->rad=rad;}show_rad(void) {<<«radius__=__>«<<rad<< endl;

};

};afto:public koleso

{:spisok[20];(char*spisok, double rad):koleso(rad)

{>rad=rad;(this->spisok, spisok);

}set_iz1 ()

{>rad=rad;(this->spisok, spisok);

}show_ss(void)

{<<«radius__=__>«<<rad<< endl;<<«firma proizvoditelya__=__>«<<spisok<<endl;

};

};gruzavto: public afto {:pod;(double rad, char*spisok, double pod): afto (spisok, rad)

{>pod=pod;>rad=rad;(this->spisok, spisok);

}set_ss() {this->rad=rad;(this->spisok, spisok);>pod=pod;}show_ss3 (void)

{<<«radius____=___>«<<rad<< endl;<<«firma proizvoditelya__=___>«<<spisok<<endl;<<«podem___=__>«<<pod<<endl;

};

};main(void)

{int d;<< «vesti novi radius??? da=1 net=2»<<endl;>>d;(d==1) {<< «vvedite radius»<<endl;>>rad;.set_rad(rad);.show_rad();}{;}

}<< "________________koleso»<<endl;.show_rad();a1 (spisok, rad);<< "________________avto»<<endl;.show_ss();(t=true) {d;<<«vvesti noviq spisok???? da=1, net=2; «<<endl;>>d;(d==1) {<< «vvedite noviy spisok»<<endl;>>spisok;a1 (spisok, rad);.show_ss();}{;}

}a2 (rad, spisok, pod);<< "____gruzovoeavto»<<endl;.show_ss3 ();(t=true)

{int d;<<«vvestinoviy podem??? da=1, net=2; «<<endl;>>d;(d==1) {cout<< «vvedite noviy podyem»<<endl;>>pod;a2 (rad, spisok, pod);.show_ss3 ();

}{;}}<< "________________gruzovik»<<endl;.show_ss3 ();(«pause»);0;

}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Цели работы:

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

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

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

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

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

#include<iostream>      namespace std;Student {mark;imya[20];fam[20];:Set_student (int mark, char *imya, char*fam)

{strcpy (this->imya, imya);(this->fam, fam);>mark=mark;

}show_1 () {<< "__"<< "="<<mark<<endl;<< "__"<< «Imya=»<<imya<<endl;<< "__"<< «familiya=»<<fam<<endl;};

};Worker {salary;stag;:Set_Worker (int salary, double stag) {>salary=salary;>stag=stag;

}show_2 () {<< "__"<< «zarplata=»<<salary<<endl;<< "__"<< «stag=»<<stag<<endl;}

};Practicant: public Student, public Worker

{char srok[20];ozenka;:set_practicant (char*srok, int ozenka)

{strcpy (this->srok, srok);>ozenka=ozenka;

}show_3 () {<< "__"<< «srok=»<<srok<<endl;<< "__"<< «ozenk=»<<ozenka<<endl;

}

};main() {s, w;. Set_student (1222, «Kolya», «kinim»);.show_1 ();.set_practicant («11juli», 12);.show_3 ();<< "___"<<endl;. Set_Worker (12333,13);.show_2 ();.set_practicant («11avg», 12);.show_3 ();0;

}

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


#include <iostream>

#include <string.h>namespace std;chel

{:pol[20];(char *pol) {(this->pol, pol);

}set_pol (char*pol)

{strcpy (this->pol, pol);}show_pol(void) {<<«pol__=__>«<<pol<< endl;

};

};student:public chel

{:stip;imya[20];(char*imya, double stip, char*pol):chel(pol)

{(this->pol, pol);(this->imya, imya);>stip=stip;

}set_iz1 ()

{>stip=stip;(this->pol, pol);(this->imya, imya);

}show_01 (void)

{<<«stip__=__>«<<stip<< endl;<<«pol__=__>«<<pol<<endl;<<«imya__=__>«<<imya<<endl;

};

};worck:public chel {:zarp;stag[20];(char*stag, double zarp, char*pol):chel(pol)

{(this->pol, pol);(this->stag, stag);>zarp=zarp;

}set_z2 ()

{>zarp=zarp;(this->pol, pol);(this->stag, stag);

}show_02 (void)

{<<«zarp__=__>«<<zarp<< endl;<<«pol__=__>«<<pol<<endl;<<«stag__=__>«<<stag<<endl;

};

};pract: public worck {:ozen;srok[20];(double ozen, char*srok, char*stag, double zarp, char*pol):worck (stag, zarp, pol)

{strcpy (this->pol, pol);(this->stag, stag);>zarp=zarp;>ozen=ozen;(this->srok, srok);

}set_ss() {this->ozen=ozen;(this->srok, srok);(this->stag, stag);>zarp=zarp;(this->pol, pol);}show_ss3 (void)

{<<«ozenka____=___>«<<ozen<< endl;<<«srok sdachi__=___>«<<srok<<endl;<<«stag__=__>«<<stag<<endl;<<«zarplata__=__>«<<zarp<<endl;<<«pol__=__>«<<pol<<endl;

};

};main(void)

{stip;<< «stip»<<endl;>>stip;zarp;<< «zarplata»<<endl;>>zarp;pol[20];<< «pol»<<endl;>>pol;imya[20];<< «vvedite imya»<<endl;>>imya;stag[20];<< «vvediter stag»<<endl;>>stag;ozen;<< «vvedit ozenku»<<endl;>>ozen;srok[20];<< «vvedite srok»<<endl;>>srok;a(pol);<< "________________chel»<<endl;.show_pol();a1 (imya, stip, pol);<< "________________student»<<endl;.show_01 ();a3 (stag, zarp, pol);<< "________________worck»<<endl;.show_02 ();a2 (ozen, srok, stag, zarp, pol);<< "_________________pract»<<endl;.show_ss3 ();(«pause»);0;

}

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

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

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

2)

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

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

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

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

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

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

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

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

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

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

Цели работы:

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

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

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

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

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

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

Задания

Вариант 1

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

#include<iostream>namespace std;worker {:i;(double x) {i=x;}void func() {cout<< «zarplata standartnogo rabochego»<<endl;<<i;}

};stateworker:public worker {:(double x):worker(x){}func() {cout<< «zarplata stateworker»<<endl;<<i*1.5<<endl;}};

horlyworker:public worker {:(double x):worker(x){}func() {<< «zarplata horlyworker»;<<i*2<<endl;

}};communicationworker:public worker {:(double x):worker(x){}func() {cout<< «zarplata communicationworker»<<endl;<<i*2.5<<endl;}};main() {*p;ob(1000);d_ob1 (1000);d_ob2 (1000);d_ob3 (1000);=&ob;>func();=&d_ob1;>func();=&d_ob2;>func();=&d_ob3;>func(); 0;

}

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

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

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

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

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

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

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

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

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

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

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


Не нашли материал для своей работы?
Поможем написать уникальную работу
Без плагиата!