Osnovni koncepti objektno orijentisanog programiranja u jeziku C++

Prema Alan Kay-u, čisto pristup objekt orijentisanom programiranju poseduje pet esencijalnih karakteristika:

  • Sve je objekat. Posmatrajmo objekat kao sofisticiranu promenljivu koja omogučava: uskladištenje vrednosti i podršku operacijama nad tom vrijednošću.
  • Program se transformiše u skup objekata koji sarađuju razmenom poruka. Poruku možemo posmatrati kao mehanizam poziva operacije nad objektima.
  • Svaki složeni objekat je izveden kao kolekcija objekata.
  • Svaki objekat pripada određenom tipu tj. predstavlja instancu KLASE (tip = klasa).
  • Svi objekti iste klase mogu primati iste poruke – polimorfizam.

U ovom delu biće dat kratak i sasvim površan pregled osnovnih koncepata OOP koje podržava C++. Potpuna i precizna objašnjenja koncepata biće objašnjena na posebnim stranicama.

Primeri koji su prikazani nisu usmereni da budu upotrebljivi, već samo pokazni. Iz realizacije primera izbačeno je sve što bi smanjivalo preglednost osnovnih ideja. Zato su primeri često i nekompletni.

Čitalac ne treba da se trudi da posle čitanja strogo zapamti sintaksu rešenja, niti da otkrije sve pojedinosti koje se kriju iza njih. Cilj je da čitalac samo stekne osećaj o osnovnim idejama OOP-a i
jezika C++, da vidi šta je to novo i šta se sve može uraditi, kao i da proba da sebe "natera" da razmišlja na novi, objektni način.


1. Klase

Klasa (class) je osnovna organizaciona jedinica programa u OOP, pa i u jeziku C++.
Klasa predstavlja strukturu u koju su grupisani podaci i funkcije:

    class Osoba {
        public:
            void predstaviSe(); 
 
        private:
            char *ime;
            int godine; 
};
void 
Osoba::predstaviSe () {
    cout<<"Ja sam "<<ime<<" i imam "<<god<<" godina.\n";
}

Klasom se definiše novi, korisnički tip za koji se mogu kreirati instance (primerci, promenljive).
Instance klase nazivaju se objekti (objects). Svaki objekat ima one svoje sopstvene elemente koji su navedeni u deklaraciji klase. Ovi elementi klase nazivaju se članovi klase (class members). Članovima se pristupa pomoću operatora "." (tačka):

    Osoba Pera, mojOtac, direktor;
 
    Pera.predstaviSe();
    mojOtac.predstaviSe();
    direktor.predstaviSe();

Specifikator public: govori prevodiocu da su samo članovi koji se nalaze iza njega pristupačni spolja. Ovi članovi nazivaju se javnim.
Članovi iza specifikatora private: su nedostupni korisnicima klase (ali ne i članovima klase) i nazivaju se privatnim


1.1 Konstruktori i destruktori

Da bi se omogućila inicijalizacija objekta, u klasi se definiše posebna funkcija koja se implicitno (automatski) poziva kada se objekat kreira (definiše). Ova funkcija se naziva konstruktor (constructor) i nosi isto ime kao i klasa:

    class Osoba {
        public:
            Osoba(char *ime, int godine);         // konstruktor 
            void predstaviSe(); 
 
        private:
            char* ime; 
            int     god; 
};
 
void 
Osoba::prestaviSe () {
    cout<<"Ja sam "<<ime<<" i imam "<<god<<" godina.\n";
}
 
Osoba::Osoba (char* i, int g) {
    ime=i;
    god=g;
}

Korišćenje klase Osoba sa ovim konstruktorom:

    Osoba Pera("Petar Markovic",25),         // poziv konstruktora osoba
    mojOtac("Slobodan Milicev",58);
    Pera.predstaviSe();
    mojOtac.predstaviSe();

Pored konstruktora moguće je definisati i funkciju koja se poziva uvek kada objekar prestaje da živi.
Ova funkcija naziva se destruktor.


2. Nasleđivanje

Pretpostavimo da nam je potreban novi tip, Maloletnik.
Maloletnik je "jedna vrsta" osobe, odnosno "poseduje sve što i osoba, samo ima još nešto", ima staratelja. Ovakva relacija između klasa naziva se nasleđivanje.

Kada nova klasa predstavlja "jednu vrstu" druge klase (a-kind-of), kaže se da je ona izvedena iz osnovne
klase:

class Maloletnik : public Osoba {
    public:
        Maloletnik (char*,char*,int); // konstruktor
        void koJeOdgovoran();
    private:
        char *staratelj;
};
 
void 
Maloletnik::koJeOdgovoran (){
    cout<<"Za mene odgovara "<<staratelj<<".\n";
}
 
Maloletnik::Maloletnik (char *i, char *s, int g) : Osoba(i,g), staratelj(s) {}

Izvedena klasa Maloletnik ima sve članove kao i osnovna klasa Osoba, ali ima još i članove staratelj i koJeOdgovoran.
Konstruktor klase Maloletnik definiše da se objekat ove klase kreira zadavanjem imena, staratelja i godina, i to tako da se konstruktor osnovne klase Osoba (koji inicijalizuje ime i godine) poziva sa odgovarajućim argumentima.
Sam konstruktor klase Maloletnik samo inicijalizuje staratelja.

Sada se mogu koristiti i nasleđene osobine objekata klase Maloletnik, ali su na raspolaganju i njihova
posebna svojstva kojih nije bilo u klasi Osoba:

    Osoba otac("Petar Petrovic",40);
    Maloletnik dete("Milan Petrovic","Petar Petrovic",12);
    otac.predstaviSe();
    dete.predstaviSe();
    dete.koJeOdgovoran();
    otac.koJeOdgovoran(); // ovo je naravno greska

3. Polimorfizam

Pretpostavimo da nam je potrebna nova klasa žena, koja je "jedna vrsta" osobe, samo što još ima i devojačko prezime. Klasa Zena biće izvedena iz klase Osoba.
I objekti klase Zena treba da se "odazivaju" na funkciju predstaviSe(), ali je teško pretpostaviti da će jedna dama otvoreno priznati svoje godine. Zato objekat klase Zena treba da ima funkciju predstaviSe(), samo što će ona izgledati malo drugačije, svojstveno izvedenoj klasi Zena:

class Osoba {
    public:
        Osoba(char*,int)              // konstruktor
        virtual void predstaviSe();         // virtuelna funkcija
    protected:                         // dostupno naslednicima
        char *ime; 
        int god;
};
 
void 
Osoba::prestaviSe () {
    cout<<"Ja sam "<<ime<<" i imam "<<god<<" godina.\n";
}
 
Osoba::Osoba (char *i, int g) : ime(i), god(g) {}
 
class Zena : public osoba {
    public:
        Zena(char*,char*,int);
        virtual void predstaviSe();         // nova verzija funkcije predstaviSe
    private:
        char *devojacko;
};
void
Zena::prestaviSe () {
    cout<<"Ja sam "<<ime<<", devojacko prezime "<<devojacko<<".\n";
}
 
Zena::Zena (char *i, char *d, int g) : Osoba(i,g), devojacko(d) {}

Funkcija članica koja će u izvedenim klasama imati nove verzije deklariše se u osnovnoj klasi kao virtuelna
funkcija (virtual). Izvedena klasa može da ima svoju definiciju virtuelne funkcije, ali i ne mora. U izvedenoj klasi ne mora se navoditi reè virtual.
Da bi članovi osnovne klase Osoba bili dostupni izvedenoj klasi Zena, ali ne i korisnicima spolja, oni se
deklarišu iza specifikatora protected: i nazivaju zaštićenim članovima.

Drugi delovi programa, korisnici klase Osoba, ako su dobro projektovani, ne moraju da vide ikakvu promenu
zbog uvođenja izvedene klase. Oni uopšte ne moraju da se menjaju:

// Funkcija "ispitaj" propituje osobe i ne mora da se menja
 
void
ispitaj (Osoba *hejTi) {
    hejTi->predstaviSe();
}
    Osoba otac("Petar Petrovic",40);
    Zena majka("Milka Petrovic","Mitrovic",35);
    Maloletnik dete("Milan Petrovic","Petar Petrovic",12);
 
    ispitaj(&otac);     //pozvaće se Osoba::predstaviSe()
    ispitaj(&majka);    //pozvaće se Zena::predstaviSe() 
    ispitaj(&dete);        //pozvaće se Osoba::predstaviSe()
 
/* Izlaz će biti:
Ja sam Petar Petrovic i imam 40 godina.
Ja sam Milka Petrovic, devojacko prezime Mitrovic.
Ja sam Milan Petrovic i imam 12 godina.

Funkcija ispitaj(Osoba* hejTi) dobija pokazivač na tip Osoba.
Kako je i žena osoba, C++ dozvoljava da se pokazivač na tip Zena (&majka) konvertuje (pretvori) u pokazivač na tip Osoba (hejTi).
Mehanizam virtuelnih funkcija obezbeđuje da funkcija ispitaj(Osoba* hejTi), preko pokazivača hejTi, pozove pravu verziju funkcije predstaviSe().
Zato će se :
za argument &majka pozivati funkcija Zena::predstaviSe(),
za argument &otac funkcija Osoba::predstaviSe,
a za argument &dete takođe funkcija Osoba::predstaviSe(), jer klasa Maloletnik nije redefinisala virtuelnu funkciju predstaviSe().

Navedeno svojstvo da se odaziva prava verzija funkcije klase čiji su naslednici dali nove verzije naziva se polimorfizam (polymorphism).


Add a New Comment
or Sign in as Wikidot user
(will not be published)
- +
Unless otherwise stated, the content of this page is licensed under GNU Free Documentation License.