Изведене класе

Да се подсетимо:

појмови се групишу на основу заједничких особина
унутар једне групе могуће је даље груписање на основу неких специфичнијих заједничких особина => сви објекти дате подгрупе имају све особине своје (основне) групе, али и још неке специфичне особине

примери:
1.
геометријске фигуре у равни описују: положај, оријентација, површина, обим…
кругови су геометријске фигуре у равни које додатно описује полупречник
квадрати су геометријске фигуре у равни које додатно описује дужина странице
троуглови су геометријске фигуре у равни које додатно описују дужине страница

2. возила служе за превоз ствари
летелице су возила која лете (авиони, хеликоптери, ракете, васионски бродови…)
пловила су возила која плове по води (чамци, једрењаци, бродови…)
сувоземна возила су возила која се крећу по земљи (бицикли, мотори, аутомобили…)

У програмском језику C++ групе објеката се описују помоћу класа:

1. Класе које описују општију групу објеката су називају се основне класе (наткласе, родитељи, преци). Ми ћемо користити појам основне класе
2. Класе које описују подгрупу објеката са неким додатним, специфичнијим особинама називају се изведене класе (поткласе, деца, потомци). Ми ћемо користити појам изведене класе

Може постојати више корака извођења класа => класа која је основна класа за неку изведену класу може бити изведена класа из неке друге класе. На пример авион може бити изведена класа из класе летелица, која има особину да поседује моторе и крила, хеликоптер може бити изведена класа из класе летелица која иа особину да поседује елису…

Дефинисање изведених класа

Изведене класе се дефинишу у наредби class чији је општи облик:

class Ime_klase : public osnovna_Klasa, … , public osnovna_Klasa
{
clan clan ...
public: clan clan …
protected: clan clan …
private: clan clan …
…
};

: иза имена класе означавају да се ради о изведеној класи. Иза : наводе се идентификатори основних класа (једна класа може бити изведена из више основних класа)

Чланове изведене класе чине чланови (подаци и методе) њених основних класа (они се не наводе у телу изведене класе, подразумевано су њени чланови) и њени сопствени чланови који се декларишу унутар класе. Због тога се каже да изведена класа наслеђује све чланове својих основних класа. Ако се класа изводи из више основних класа у питању је вишеструко наслеђивање.

Конструктори, деструктор и метода operator= основне класе се не наслеђују; већ се генеришу, ако је то потребно.

Од конструктора генеришу се подразумевани конструктор и конструктор копије. Подразумевани конструктор има празно тело. Конструктор копије врши копирање вредности свог аргумента у објекат који се ствара, и то податак по податак. Генерисани деструктор има празно тело. Овако генерисани конструктори и деструктор омогућавају позивање евентуалних конструктора и деструктора основних класа. Детаљније у Стварање и уништавање примерака изведених класа.

Генерисана метода operator= додељује вредност податак по податак. То је основно тумачење оператора = без преклапања оператора. Подаци класних типова додељују се операторским функцијама за доделу вредности својих класа. Наслеђени подаци основних класа додељују се операторским функцијама за доделу вредности својих основних класа.

Контрола приступа члановима класе остварује се уметањем ознака public, protected и private. Тиме се класа дели на јавне, заштићене и приватне делове. Јавним члановима приступ је могућ без ограничења. Заштићеним члановима може се приступати из саме класе и из свих класа изведених из ње. Приватним члановима могућ је приступ само из дате класе.
Свака класа може да прогласи неке функције које нису њени чланови, као и целе класе, својим пријатељима.
Пријатељске функције и/или класе имају неограничен приступ свим члановима класе. „Пријатељство” се не наслеђује. Пријатељ основне класе не постаје аутоматски пријатељ класе која је из ње изведена. Ако желимо да морамо те пријатеље дефинисати као пријатеље и у изведеној класи.

Модификатор public испред идентификатора основне класе означава јавно извођење, што значи да степен заштите свих наслеђених чланова остаје непромењен: јавни чланови основне класе остају јавни и у изведеној класи, заштићени чланови остају заштићени, а приватни остају приватни. Сви јавни чланови основне класе постају јавни чланови изведене класе. Због тога над објектима изведене класе могу да се изводе све радње као и над објектима основне класе, али и још неке друге радње које постоје само у изведеној класи.

Дијаграми класа за изведене класе

izvedenaklasa1

Линије су оријентисане од изведене ка основној класи (у основној класи се не зна које све изведене класе постоје, али зато у изведеној класи увек се зна из којих класа је изведена). Дуж линија извођења могу да се сагледају сви чланови који постоје у објекту неке изведене класе.

На врху слике цртају се основне класе. Испод њих се налазе изведене класе. Сваки слој обележава један корак извођења.

Пример:

class A {int a;};
class B {int b;};
class C:public A {int c;};
class D:public A, public B {int d;};
class E:public D {int e;};

izvedeneklase2Објекти класе C имају два податка: свој сопствени податак c и податак a који је наслеђен из класе A. Објекти класе D имају податке: d, a и b. Објекат класе E наслеђује све податке класе D, и његове сопствене и наслеђене, тако да има податке: a, d, a и b.

Употреба чланова изведених класа

Члановима основних класа неке изведене класе приступа се као и њеним сопственим члановима:

унутар класе довољан је само идентификатор члана
изван класе користе се изрази: изведени_објекат.члан или изведени_показивач.члан

izvedeneklase3Редефинисање идентификатора унутар изведене класе покрива истоимени члан основне класе. Члану основне класе приступа се применом оператора за разрешење досега: основнаКласа::члан

Преклапањем метода основне класе оне постају невидљиве у изведеној класи што значи да се могу користити само методе дефинисане у изведеној класи.

Стварање и уништавање примерака изведених класа

Стварање примерка изведене класе:

извршавају се конструктори основних класа по редоследу навођења основних класа у дефиницији изведене класе. За иницијализацију поља користе се конструктори одговарајућих класа
извршавају се конструктори поља класних типова по редоследу навођења поља у дефиницији изведене класе. За иницијализацију поља користе се конструктори одговарајућих класа
иницијализују се поља стандардних типова
извршава се тело конструктора изведене класе. За иницијализацију класних поља основних класа користи се operator =

Уништавање објеката изведене класе:

извршава се деструктор изведене класе
извршавају се деструктори поља класних типова, обрнуто од редоследа извршавања конструктора
извршавају се деструктори основних класа, обрнуто од редоследа позивања конструктора тих класа


class Osn1 // prva osnovna klasa  {
       int *a;  
public:       Osn1():a(0){}  
}; class Osn2 // druga osnovna klasa  {       char *b;       
double c;  
public:       
Osn2(){b=0;c=5;}       Osn2(char *x,double y):c(y){b=x;}  };   class Izv:public Osn2,public Osn1 // klasa izvedena iz dve osnovne klase  {       int p,q;    
   Osn1 r;   
    Osn2 s,t;    
   double u,v;  public:       Izv(int x, char *y,double z):p(x+2),Osn2(y,z),s("ne",x){q=p+z;}  };  
 int main()  {       Izv k(1,"Zdravo",2); // objekat izvedene klase  } 

Ток иницијализације објекта k у главној функцији је следећи:

Osn2("zdravo",2.0) -> k.c=2.0                       k.b="Zdravo"  
Osn1()            -> k.a=0  
r.Osn1()          -> k.r.a=0  
s.Osn2("ne",1.0)  -> k.s.c=1.0            
           k.s.b="ne"  
t.Osn2()          -> k.t.b=0    
                   k.t.c=5.0  p(3)              -> k.p=3  q=3+2.0           -> k.q=5

поља k.u и k.v остају неиницијализована јер за њих нису наведени ни иницијализатори, нити су им додељене вредности у телу конструктора.

Конверзија типа између основних и изведених класа

Објекат основне класе може да се иницијализује објектом изведене класе. Конструктор копије основне класе копира само поља изведене класе која су наслеђена од основне класе.

Објекту основне класе може да се додељује вредност објекта изведене класе. Операторска функција за доделу вредности основне класе копира само поља изведене класе која су наслеђена од основне класе.

За иницијализацију објекта изведене класе објектом основне класе, односно за доделу вредности објекта основне класе објекту изведене класе мора постојати дефинисана конверзија основне класе у изведену класу. Обично се користи констурктор конверзије који дефинише вредности специфичних поља изведене класе која не постоје у основној класи.

Показивачу po на објекте основне класе Osn може да се додели вредност показивача piна објекте изведене класе Izv зато што се израз po=pi тумачи као po=(Osn*)pi

Додела вредности показивача на основне класе показивачу на објекте изведене класе могућа је искључиво уз помоћ експлицитне конверзије, односно изразом pi=(Izv*)po.

У дијаграмима класа основне класе се цртају изнад изведених па се конверзија показивача на основну класу у показивач на изведену класу назива конверзија на доле, а конверзија показивача на изведену класу у показивач на основну класу назива се конверзија на горе.

1. Подаци о особи су име, датум рођења и адреса становања. Ђак је особа за коју се додатно знају назив школе и разред који похађа. Запослени је особа за коју се додатно знају назив фирме и назив одељења.
Написати класе које омогућавају унифицирану обраду података о набројаним категоријама особа. Сва поља су стрингови фиксних дужина. Предвидети иницијализацију примерака класа празним стринговима, уношење података у њих читањем са главног улаза и приказивање њиховог садржаја писањем на главном излазу.
Написати програм за проверу исправности претходних класа.

// osobe.h - Klase osoba, djaka i zaposlenih
#include 
using namespace std;
class Osoba
{
	char ime[31], datum[11], adresa [31];
public:
	Osoba () { ime[0] =datum[0]=adresa[0] =0;}
	virtual void citaj ( )
	{
		cout << "Ime i prezime?"; cin >> ime;
		cout << "Datum rodjenja?"; cin >> datum;
		cout << "Adresa stanovanja? "; cin >> adresa;
	}
	virtual void pisi () const
	{
		cout << "Ime i prezime:" << ime<<endl;
		cout << "Datum rodjenja:" << datum<<endl;
		cout << "Adresa stanovanja: " << adresa<< endl;
	}
};

class Djak: public Osoba
{
	char skola [31], razred[7] ;
public:
	Djak (): Osoba() { skola[0]=razred[0]=0;}
	void citaj ()
	{
		Osoba::citaj ();
		cout << "Naziv skole?";cin>>skola;
		cout << "Razred?"; cin>>razred;
	}
	void pisi () const
	{
		Osoba ::pisi ();
		cout << "Naziv skole:"<<skola<<endl;
		cout << "Razred:"<<razred<<endl;
	}
};

class Zaposleni: public Osoba
{
	char firma [31] , odeljenje [31];
public:
	Zaposleni (): Osoba() { firma [0] = odeljenje [0]=0;}
	void citaj ()
	{
		Osoba::citaj ();
		cout << "Naziv firme?";cin>>firma;
		cout << "Naziv odeljenja?";cin>>odeljenje;
	}
	void pisi () const
	{
		Osoba::pisi ();
		cout << "Naziv firme:"<<firma<<endl;
		cout << "Naziv odeljenja:"<<odeljenje<<endl;
	}
};

// glavni program
#include "osobe.h"
#include 
using namespace std;
int main ()
{
	Osoba *ljudi[20]; int n=0;
	cout << "Citanje podataka o ljudima\n(ime i prezime uneti kao jednu rec, izmedju imena i prezimena koristiti _!)";
	while (true)
	{
		cout << "\nIzbor (O=osoba, D=djak, Z=zaposleni, K=kraj) ? "; 		char izbor; cin >> izbor;
		if (izbor=='K' || izbor=='k' ) break;
		ljudi[n] = 0;
		switch (izbor)
		{
			case 'O': case 'o':ljudi [n] = new Osoba;break;
			case 'D':case 'd':ljudi[n] = new Djak;break;
			case 'Z' : case 'z':ljudi[n] = new Zaposleni;break;
		}
		if (ljudi [n] ) ljudi [n++] ->citaj();
	}
	cout << "\nPrikaz procitanih podataka\n";
	for (int i=0; i<n; i++) { cout << endl; ljudi[i]->pisi();}
	return 0;
}

 

Оставите одговор

Попуните детаље испод или притисните на иконицу да бисте се пријавили:

WordPress.com лого

Коментаришет користећи свој WordPress.com налог. Одјавите се /  Промени )

Google photo

Коментаришет користећи свој Google налог. Одјавите се /  Промени )

Слика на Твитеру

Коментаришет користећи свој Twitter налог. Одјавите се /  Промени )

Фејсбукова фотографија

Коментаришет користећи свој Facebook налог. Одјавите се /  Промени )

Повезивање са %s