konstruktor destruktor
DESCRIPTION
Konstruktori i destruktori u programiranju.TRANSCRIPT
Programski jezici 1
1. dio
mr Dražen Brđanin
Elektrotehnički fakultetBanja Luka
2009
KLASE I APSTRAKCIJA PODATAKA
Klase – 1. dio
Sadržaj Razlike C/C++ programiranja Osnovne karakteristike klase Definisanje klase Specifikatori pristupa članovima klase Razlike između definicije i deklaracije klase Oblast definisanosti i pristup članovima klase Pomoćne funkcije u klasi Modularizacija Inicijalizacija objekata – konstruktori Destruktori Redoslijed izvršavanja konstruktora i destruktora
Osnovne razlike C i C++ programiranja
Programiranje u jeziku C Proceduralno (algoritamski)
orijentisano
Jedinica programiranja – FUNKCIJA
Programeri se koncentrišu na pisanje funkcija, funkcije se grupišu u program
Podaci nisu primarni, oni su u funkciji podrške akcijama koje funkcije izvode
Glagoli određuju šta sistem radi i koje će funkcije biti implementirane
Instance ugrađenih tipova (int, char, …) nazivaju se promjenljive (varijable)
Programiranje u jeziku C++
Objektno orijentisano
Jedinica programiranja – KLASA
Programeri se koncentrišu na kreiranje vlastitih tipova podataka – KLASE
Imenice su te koje određuju sistem (imenice određuju klase)
Svaka klasa sadrži podatke i funkcije za manipulaciju podacima
Podaci koji se nalaze u klasi nazivaju se podaci članice (data members)
Funkcije koje se nalaze u klasi nazivaju se funkcije članice (metode)
Instance korisnički definisanih tipova (klasa) nazivaju se objekti
Osnovne karakteristike klase
KLASA omogućava modelovanje objekata, koje karakterišu: atributi (podaci članice – data members)
ponašanje ili operacije (funkcije članice – member functions)
U nekim OO programskim jezicima funkcije članice se nazivaju
metode.
Najvažnije karakteristike KLASE kao pravog tipa podataka: Određuju moguće vrijednosti objekata,
Određuju moguće operacije nad objektima,
Obezbjeđuju obaveznu inicijalizaciju objekata pri njihovom stvaranju,
Obezbjeđuju uništavanje objekata kada više nisu potrebni,
Obezbjeđuju enkapsulaciju atributa i ponašanja u jedinstevnu cjelinu,
Omogućavaju princip skrivanja informacija (information hiding).
Definisanje klase
KLASA se definiše korišćenjem ključne
riječi class.
Uobičajeno naziv klase započinje velikim slovom.
Opšti oblik definicije klase
class Ime
{
tip clan;
…
public:
tip clan;
…
private:
tip clan;
…
};
javni članovi klase
privatni članovi klase
privatni članovi klase
privatni članovi klase
javni članovi klase
Primjer definicije klase
class Razlomak
{
public:
Razlomak();void
setBrojilac(int b);void
setImenilac(int n);void
printRazlomak();float vrijednost();
private:
int brojilac;int imenilac;
};
Funkcije članice najčešće su javni
članovi klase
Podaci članice najčešće su privatni
članovi klase (skrivanje
informacija)
Specifikatori pristupa članicama klase
public Sve članice definisane iza
specifikatora public: su javne.
Javna članica klase dostupna je iz bilo kojeg dijela programa u kojem je dostupan objekat date klase.
Javna članica dostupna je i iz unutrašnjosti klase.
Uobičajeno su funkcije članice javne članice klase (funkcije opisuju ponašanje, odnosno operacije nad objektima).
private Sve članice definisane iza
specifikatora private: su privatne.
Privatnoj članici klase ne može se pristupiti spolja, već samo iz unutrašnjosti klase.
Privatnoj članici klase pristupa se posredstvom funkcija članica te klase.
Privatnoj članici klase mogu da pristupe i tzv. prijatelji klase, tj. prijateljske funkcije klase.
Uobičajeno su podaci članice privatni članovi klase (princip skrivanja informacija).
Postoje i protected (zaštićeni) članovi klase – primjenjuje se
kod nasljeđivanja.
Specifikatori pristupa:
• mogu da mijenjaju mjesta,
• mogu više puta da se navode,
• ako se izostavi, podrazumijeva se private.
Definicija klase <-> Deklaracija klase
Definicija klase podrazumijeva navođenje svih članica klase.
Deklaracija klase podrazumijeva da se samo naznači (deklariše) da neki identifikator predstavlja klasu.
Opšti oblik deklaracije klase:
class Ime;
Kad je klasa definisana, mogu se definisati (kreirati) i njene instance (objekat, niz objekata, upućivač, pokazivač na objekat).
Primjer:
Klasa objekat;Klasa objekat;
Klasa nizKlasa niz[100];[100];
Klasa *pointer;Klasa *pointer;
Klasa &upucivac = Klasa &upucivac = objekat;objekat;
Ako je poznata samo deklaracije klase ne mogu se instancirati objekti, već mogu samo da se definišu pokazivači.
Definicija funkcija članica klase
Funkcije članice mogu da se definišu unutar klase.
Funkcije članice mogu da se definišu izvan klase, ali se unutar klase treba navesti njihov prototip. Primjer:
class class CounterCounter {{ private:private:
int count;int count; public:public:
......void printvoid print() ()
{ { cout << cout << countcount;;
}}......
};};
Primjer:
class class CounterCounter {{
private:private:int count;int count;
public:public:......void printvoid print()();; ......
};};
void void CounterCounter::print()::print()
{ { cout << cout << countcount;; }}
Praksa pokazuje da je bolje unutar klase navesti samo prototip, a funkciju članicu definisati izvan
funkcije.
Oblast definisanosti i pristup članovima
Članice klase dostupne su svim ostalim članicama date klase. Referenciraju se navođenjem imena članice.
Izvan klase, članice klase mogu da se referenciraju pomoću: objekta - objekat.clanica pokazivača na objekat - pokazivac->clanica ili
(*pokazivac).clanica upućivača na objekat - upucivac.clanica
Promjenljive definisane u nekoj funkciji članici vidljive su samo u toj funkciji.
Ako je unutar funkcije članice definisana promjenljiva sa istim imenom kao neki podatak član klase, onda lokalna promjenljiva maskira podatak član.
Pristup maskiranom atributu preko operatora za razrješavanje dosega (::).
Oblast definisanosti i pristup članovima
Primjer:
#include <iostream.h>#include <iostream.h>
class Counterclass Counter{{ public:public: int x;int x; void print() { cout << x << endl; }void print() { cout << x << endl; }};};
main()main(){{ Counter c; Counter c; // kreira objekat c (instanca klase Counter)// kreira objekat c (instanca klase Counter) Counter *pc = &c; Counter *pc = &c; // pointer na c// pointer na c Counter &uc = c; Counter &uc = c; // upucivac na c// upucivac na c
c.x = 7; c.x = 7; // postavlja vrijednost atributa objekta// postavlja vrijednost atributa objekta c.print(); c.print(); // direktan poziv funkcije članice// direktan poziv funkcije članice
uc.x = 8; uc.x = 8; // postavlja vrijednost pomocu upucivaca// postavlja vrijednost pomocu upucivaca uc.print(); uc.print(); // poziv funkcije pomocu upucivaca// poziv funkcije pomocu upucivaca
pc->x = 10; pc->x = 10; // postavlja vrijednost pomocu pointera// postavlja vrijednost pomocu pointera pc->print(); pc->print(); // poziv funkcije pomocu pointera// poziv funkcije pomocu pointera}}
7810
Podatak član x je javni atribut. Ovo treba izbjegavati!
Ovdje je korišćeno samo radi ilustracije pristupa!
Oblast definisanosti i pristup članovima
Primjer:
#include <iostream.h>#include <iostream.h>int x; // globalna promjenljivaint x; // globalna promjenljivaclass Klasaclass Klasa{{ public:public: void set(int i) { x=i; }void set(int i) { x=i; } void primjer();void primjer(); private:private: int x; // podatak clanint x; // podatak clan};};void Klasa::primjer()void Klasa::primjer(){{ int x=1; // lokalna promjenljivaint x=1; // lokalna promjenljiva cout << "Lokalno x: " << x << endl;cout << "Lokalno x: " << x << endl; cout << "Atribut x: " << Klasa::x << endl;cout << "Atribut x: " << Klasa::x << endl; cout << "Globalno x: " << ::x;cout << "Globalno x: " << ::x;}}main()main(){{ Klasa t;Klasa t; t.set(100);t.set(100); t.primjer();t.primjer();}}
Lokalno x: 1Atribut x: 100Globalno x: 0
Oblast definisanosti i pristup članovima
Primjer:
#include <iostream.h>#include <iostream.h>
class Timeclass Time{{ public:public: void setTime(int, int, int);void setTime(int, int, int); void printM();void printM(); void printS();void printS(); private:private: int sat, min, sek;int sat, min, sek;};};
void Time::setTime(int h, int m, int s)void Time::setTime(int h, int m, int s){{ sat = ( h >= 0 && h < 24 ) ? h : 0;sat = ( h >= 0 && h < 24 ) ? h : 0; min = ( m >= 0 && m < 60 ) ? m : 0;min = ( m >= 0 && m < 60 ) ? m : 0; sek = ( s >= 0 && s < 60 ) ? s : 0;sek = ( s >= 0 && s < 60 ) ? s : 0;}}
void Time::printM()void Time::printM(){{ cout << (sat<10?"0":"") << sat << ":";cout << (sat<10?"0":"") << sat << ":"; cout << (min<10?"0":"") << min;cout << (min<10?"0":"") << min;}}
void Time::printS()void Time::printS(){{ cout << ((sat==12)?12:sat%12 ) << ":";cout << ((sat==12)?12:sat%12 ) << ":"; cout << (min<10 ? "0":"") << min << ":";cout << (min<10 ? "0":"") << min << ":"; cout << (sek<10 ? "0":"") << sek;cout << (sek<10 ? "0":"") << sek; cout << (sat<12 ? “AM" : “PM" );cout << (sat<12 ? “AM" : “PM" );}}
main()main(){{ Time t;Time t; t.setTime(13t.setTime(13,,27,6);27,6); cout << "cout << "VrijemeVrijeme : "; : "; t.printM(); cout<<" ili "; t.printS();t.printM(); cout<<" ili "; t.printS(); t.setTimet.setTime((99,99,99);99,99,99); cout << "\nPokusaj : ";cout << "\nPokusaj : "; t.printM(); cout<<" ili "; t.printS();t.printM(); cout<<" ili "; t.printS();}}
Vrijeme : 13:27 ili 1:27:06 PMPokusaj : 00:00 ili 0:00:00 AM
Oblast definisanosti i pristup članovima
Privatnim članovima klase mogu da pristupe: funkcije članice date klase “prijateljske” funkcije date klase.
Tipično se implementiraju sljedeće funkcije članice: za postavljanje atributa - tzv. set
funkcijanpr. setTime, setMin, setSek
za očitavanje atributa - tzv. get funkcija npr. getSat, getMin, getSek
Primjer:
class Bankaclass Banka {{ private:private: floatfloat stanjestanje;; public:public: ...... void setStanjevoid setStanje((float nsfloat ns)) { stanje = ns; }{ stanje = ns; }
float getStanje()float getStanje() { return stanje; }{ return stanje; } ...... };}; ...... Banka racun;Banka racun; racun.setStanje(0);racun.setStanje(0); cout << racun.getStanje(); cout << racun.getStanje();
Pomoćne funkcije u klasi
Ne moraju sve funkcije članice da budu javne (pogotovo ako one nisu dio interfejsa klase).
Ako neka funkcija služi kao pomoćna funkcija (helper ili utility function) u klasi, tako da npr. nešto računa ili slično za neku drugu funkciju članicu klase, tada takvu pomoćnu funkciju ostavljamo kao privatnu.
Funkcije članice koje čine interfejs klase, odnosno omogućavaju pristup privatnim članovima klase nazivamo i pristupne funkcije (access functions).
Funkcije članice koje provjeravaju ispunjenost nekog uslova (npr. da li je podatak ovakav ili onakav, da li je štampač spreman, da li je lift zauzet i sl.) nazivaju se predikatske funkcije (predicate functions).
Modularizacija
U realizaciji većih programa preporučljivo je modularizovati kod. Pri tome interfejs klase treba odvojiti od implementacije.
primjer.h (interfejs)
#ifndef PRIMJER#ifndef PRIMJER#define PRIMJER#define PRIMJER
class Timeclass Time{{ public:public: void setTime(int, int, int);void setTime(int, int, int); void printM();void printM(); void printS();void printS(); private:private: int sat, min, sek;int sat, min, sek;};};
#endif#endif
primjer.cpp (implementacija)
#include <iostream.h>#include <iostream.h>#include "primjer.h"#include "primjer.h"
void Time::setTime(int h, int m, int s)void Time::setTime(int h, int m, int s){{ sat = ( h >= 0 && h < 24 ) ? h : 0;sat = ( h >= 0 && h < 24 ) ? h : 0; min = ( m >= 0 && m < 60 ) ? m : 0;min = ( m >= 0 && m < 60 ) ? m : 0; sek = ( s >= 0 && s < 60 ) ? s : 0;sek = ( s >= 0 && s < 60 ) ? s : 0;}}
void Time::printM()void Time::printM(){{ cout << (sat<10?"0":"") << sat << ":";cout << (sat<10?"0":"") << sat << ":"; cout << (min<10?"0":"") << min;cout << (min<10?"0":"") << min;}}
void Time::printS()void Time::printS(){{ cout << ((sat==12)?12:sat%12 ) << ":";cout << ((sat==12)?12:sat%12 ) << ":"; cout << (min<10 ? "0":"") << min << ":";cout << (min<10 ? "0":"") << min << ":"; cout << (sek<10 ? "0":"") << sek;cout << (sek<10 ? "0":"") << sek; cout << (sat<12 ? “AM" : “PM" );cout << (sat<12 ? “AM" : “PM" );}}
projekat.cpp (glavni program)
#include <iostream.h>#include <iostream.h>#include "primjer.h"#include "primjer.h"
main()main(){{ Time t; ...Time t; ...}}
Inicijalizacija objekata - KONSTRUKTORI
Konstruktor – specijalna funkcija članica koja omogućava inicijalizaciju objekta prilikom njegovog kreiranja.
Konstruktor ima isto ime kao i klasa kojoj pripada. Konstruktor nema tip – čak ni void! Konstruktor se automatski poziva svaki put kad se kreira neki objekat.
Primjer:
class Timeclass Time
{{
private:private:
int hh, mm, ss;int hh, mm, ss;
public:public:
......
Time() { hh = mm = ss = 0; }Time() { hh = mm = ss = 0; }
......
};};
......
Time Time tt;;
Inicijalizacija objekata - KONSTRUKTORI
Iako programer eksplicitno ne poziva konstruktor pri kreiranju objekta, ipak je moguće u konstruktor prenijeti parametre kojima će se inicijalizovati atributi. Ovi parametri nazivaju se inicijalizatori i navode se unutar malih zagrada prilikom definisanja objekta. Inicijalizatori predstavljaju argumente koji se prosljeđuju konstruktoru.
Primjer:
class Timeclass Time {{ private:private: int hh, mm, ss;int hh, mm, ss;
public:public: Time(int h, int m, int s) Time(int h, int m, int s) { {
hh=h; mm=m; ss=s; hh=h; mm=m; ss=s; }}
};};
… …
Time podne(12,0,0), ponoc(0,0,0); Time podne(12,0,0), ponoc(0,0,0);
Klasa ne mora da ima konstruktor. Objekti mogu da se inicijalizuju drugim
funkcijama članicama. Praksa pokazuje da je najbolje da
se objekat inicijalizuje konstruktorom.
Inicijalizacija objekata - KONSTRUKTORI
Konstruktori mogu da se preklapaju – više konstruktora sa preklopljenim imenom u klasi, što omogućava različite načine inicijalizacije objekata (različita početna stanja).
Primjer:
class Timeclass Time{{ private:private: int hh, mm, ss;int hh, mm, ss; public:public: Time(int h, int m, int s) Time(int h, int m, int s)
{ hh=h; mm=m; ss=s; }{ hh=h; mm=m; ss=s; } Time(int s) Time(int s)
{ hh=s/3600; mm=(s%3600)/60; ss=s%60; }{ hh=s/3600; mm=(s%3600)/60; ss=s%60; }};};
......
Time podne(12,0,0);Time podne(12,0,0);
Time Time petdo12(11,55petdo12(11,55,0,0));;
Time ponoc(0);Time ponoc(0);
Inicijalizacija objekata - KONSTRUKTORI
Konstruktor može da ima i podrazumijevane vrijednosti argumenata.
Primjer:
class Timeclass Time{{ private:private: int hh, mm, ss;int hh, mm, ss; public:public: Time(int hTime(int h=0=0, int m, int m=0=0, int s, int s=0=0) ) { { hh=h; mm=m; ss=s; hh=h; mm=m; ss=s; }}};};
……
Time podne(12), ponocTime podne(12), ponoc, petdo12(11,55), petdo12(11,55); ;
Inicijalizacija objekata - KONSTRUKTORI
Podrazumijevane vrijednosti mogu da se navedu u prototipu konstruktora – tada se ne navode u definiciji konstruktora!
Podrazumijevane vrijednosti mogu da se navedu u definiciji konstruktora – tada se ne navode u prototipu konstruktora!
Primjer:
class Timeclass Time {{ private:private: iint nt hh, mm, sshh, mm, ss;; public:public: ...... Time(int=0, int=0, int=0);Time(int=0, int=0, int=0); ...... };}; ...... Time::Time(int h, int m, int s)Time::Time(int h, int m, int s) {{ hh=h; mm=m; ss=s;hh=h; mm=m; ss=s; }}
Primjer:
class Timeclass Time {{ private:private: iint nt hh, mm, sshh, mm, ss;; public:public: ...... Time(int, int, int);Time(int, int, int); ......};};......Time::Time(int hTime::Time(int h=0=0, int m, int m=0=0, int s, int s=0=0)){{ hh=h; mm=m; ss=s;hh=h; mm=m; ss=s;}}
Nije dozvoljeno podrazumijevane vrijednosti navoditi i u prototipu i u definiciji konstruktora (isto važi i za ostale funkcije članice!)!
DESTRUKTORI
Destruktori – slično konstruktoru – još jedna specijalna funkcija članica klase
Destruktor se poziva svaki put kad se uništava neki objekat.
Destruktor suštinski ne uništava objekat (objekat će biti uništen i u slučaju da klasa nema definisan destruktor) - destruktor služi za “čišćenje memorije” (bitno kod objekata koji dinamički alociraju memoriju).
Klasa može da ima samo jedan destruktor. Nije dozvoljeno preklapanje imena.
Destruktor nema argumenata! Destruktor nema tip!
Destruktor ima isto ime kao konstruktor, ali se ispred stavlja tilda (~). Intuitivno se može napraviti analogija sa bitskim operatorom negacije, jer se destruktor ponaša kao komplement konstruktora.
class Timeclass Time {{
public:public: ...... ~Time()~Time();; ......
};};
Redoslijed konstruktora i destruktora
Konstruktori i destruktori se pozivaju automatski.
Redoslijed kojim se pozivaju ove funkcije zavisi od redoslijeda kojim se ulazi i izlazi iz domena u kojem se objekti kreiraju. Generalno, destruktori se pozivaju obrnutim redoslijedom u odnosu na poziv konstruktora.
Za globalne objekte: Konstruktor se poziva prije bilo koje funkcije (i prije main funkcije) – tj.
prije početka izvršavanja programa. (u slučaju više fajlova, redoslijed izvršavanja konstruktora nije unaprijed poznat!)
Destruktor se poziva nakon završetka izvršavanja main().
Za lokalne i automatske objekte: Konstruktor se poziva u trenutku kad se objekat definiše. Destruktor se poziva u trenutku napuštanja bloka u kojem je objekat
definisan.
Za statičke objekte: Konstruktor se poziva samo jednom - prilikom definisanja objekta. Destruktor se poziva samo nakon završetka izvršavanja funkcije main.
Redoslijed konstruktora i destruktora
#include <iostream.h>class KD{ public: KD(int x) { data = x; cout << "Konst " << data; } ~KD() { cout<<"Dest "<<data<<endl; } private: int data;};
void create( void ){ KD kd5(5); cout << " (create lokalni)" << endl; static KD kd6(6); cout << " (create staticki)" << endl; KD kd7(7); cout << " (create lokalni)" << endl;}
KD kd1(1); // globalni objekat
main(){ cout <<" (ulaz u main)”<< endl; KD kd2(2); cout <<" (main: lokalni)”<<endl; static KD kd3(3); cout <<" (main: staticki)”<<endl; create(); KD kd4(4); cout <<" (main: lokalni)”<<endl; cout <<"Izlaz iz programa”<<endl;}
Konst 1 (ulaz u main)Konst 2 (main: lokalni)Konst 3 (main: staticki)Konst 5 (create lokalni)Konst 6 (create staticki)Konst 7 (create lokalni)Dest 7Dest 5Konst 4 (main: lokalni)Izlaz iz programaDest 4Dest 2Dest 6Dest 3Dest 1