posljednja izmjena: 10.03.2003.

Neka proširenja C jezika

Referenca
Referenca predstavlja drugo ime neke varijable. Može se shvatiti kao pokazivač koji se koristi sa jednostavnijom sintaksom. Najčešće se koristi kao parametar funkcije ili vrijednost koju vraća funkcija.
a)  referenca kao parametar funkcije - u slučaju kad se referenca upotrebljava kao parametar funkcije, prevodilac neizravno prenosi adresu varijable.

 int funkcija(int &referenca)
 { ... }
 ...
 rezultat = funkcija(varijabla);

Ova metoda se koristi kada želimo da funkcija može promijeniti vrijednost referencirane varijable (a to se može jer referenca pokazuje na isti memorijski prostor) ili kad funkciji kao parametar šaljemo veliku strukturu koju za koju ne želimo da se kopira u memoriji.
Ako koristimo referencu za izbjegavanje kopiranja a ne želimo da se parametar može izmjeniti, poželjno je deklarirati referencu na konstantu:

 int funkcija(const int& referenca)
 { ... }

b)  funkcija koja vraća referencu - podatak koji funkcija vraća može se proslijediti kao referenca. Tako je moguće i funkciji dodijeliti neku vrijednost.

 int& funkcija(int varijabla)
 { ... }

Ovu metodu možemo koristiti npr. u funkciji preko koje možemo i dohvatiti i postaviti vrijednost neke (skrivene) varijable, kao u donjem primjeru:

double& dohvati_ili_promijeni(int index_polja)
{
    return polje[index_polja];
}
...
v = dohvati_ili_promijeni(5);    // dohvacamo element sa indexom 5
dohvati_ili_promijeni(4) = v;    // pridjeljujemo vrijednost elementu s indexom 4

Treba paziti da funkcija ne vraća referencu na lokalnu varijablu deklariranu unutar funkcije, jer tada možemo pristupiti memoriji koja više nije zauzeta. Tako se za varijablu polje u gornjem primjeru pretpostavlja da je globalnog dosega.
 

Elementi C++ jezika

Razredi i objekti
Razredi (klase) se u stvarnom životu mogu prepoznati kao opće imenice koje predstavljaju skupove elemenata sa nekim zajedničkim svojstvima (npr. vozilo, građevina, student i sl.). Objekti su pojedini elementi skupa kojega definira neki razred. Npr. jedan objekt razreda vozilo je autobus, drugi je avion, itd. Također može postojati razred avion, čiji su objekti npr. dvokrilac, mlažnjak, Boeing i sl.
U C++-u razredi se definiraju svojim pripadnim elementima:  pripadni podaci i pripadne metode (funkcije). U OOP uvodi se kontrola pristupa članovima razreda - postoje tri specifikatora pristupa koji se definiraju za grupe članova:
    public - članovi dostupni su svim funkcijama u programu
    private - članovi dostupni su samo pripadnim funkcijama istoga razreda
    protected - članovi dostupni su pripadnim funkcijama istoga razreda i pripadnim funkcijama svih razreda koji su izvedeni iz početnoga, a nisu vidljivi u ostalim funkcijama

 class Razred

 {
    public:
        int public_podatak;
        void Funkcija(void);
    private:
        double private_podatak;
    protected:
        char protected_podatak;
 }; // mora biti ; na kraju

Pripadni podatak može biti struktura, neki drugi razred, pokazivač ili referenca na neki drugi razred itd.
U definiciji razreda moraju se nalaziti deklaracije svih pripadnih metoda, dok se njihove definicije mogu nalaziti i izvan definicije razreda. U tom slučaju moramo operatorom dosega označiti o čijoj je metodi riječ.

 void Razred::Funkcija(void)
 { ... }

Ako je definicija metode napisana unutar razreda, ona će biti inline funkcija (tj. prevodilac će umetnuti tijelo te funkcije na svako mjesto gdje se ona poziva). Želimo li da funkcija koju definiramo izvan razreda bude inline, napisat ćemo ključnu riječ inline ispred imena funkcije.
Objekti definiranog razreda mogu se instancirati na više načina:

 Razred objekt;     // objekt kao lokalna varijabla
 Razred *pok;       // deklariramo pokazivac na objekt (ne i objekt!)
 pok = &objekt;     // pokazuje na postojeci
 pok = new Razred;    // stvaramo novi objekt
 delete pok;          // brisemo objekt na koji pok pokazuje

Članu definiranog razreda može se pristupiti izvan razreda:

 objekt.funkcija();
 pok->funkcija();
 pok->public_podatak = 1;

U tijelu pripadne funkcije razreda članovima istog objekta se pristupa:

 private_podatak = 0.1; // isto kao i this.private_podatak
 funkcija();            //
 this->funkcija();      // pristup preko
 (*this).funkcija();    // this pokazivaca
 drugi_objekt.public_podatak = 0;

this pokazivač služi funkciji razreda da pristupi objektu kojem pripada (npr. ako funkcija vraća objekt kao rezultat).

Konstruktor
Konstruktor je pripadna funkcija koja se izvršava pri inicijalizaciji objekta. Konstruktor ima isto ime kao i razred, nije definiranog tipa i ne vraća nikakvu vrijednost. Prevodilac sam generira pretpostavljeni konstruktor koji ne zahtijeva parametre, ukoliko programer ne napiše vlastiti. U konstruktoru se obično definiraju pretpostavljene vrijednosti parametara, zauzima memorija i sl.
Ukoliko se konstruktor poziva s parametrima, inicijalizacija podataka objekta može se obaviti listom inicijalizatora:

 // definicija izvan razreda
 Razred::Razred(int _x, int _y) : x(_x), y(_y);
 { ... }

 // gornji zapis radi pridruzivanje kao dolje:
 Razred::Razred(int _x, int _y)
 {   this.x = _x;
     this.y = _y;
 }

Kopirajući konstruktor
Kopirajući konstruktor je pripadna funkcija koja se poziva pri kopiranju objekta u memoriji. Ukoliko ne napišemo kop. konstruktor, prevodilac će generirati pretpostavljeni za naš razred. Važno: ukoliko u razredu koristimo pokazivače ili reference te ručno zauzimamo dodatnu memoriju (npr. za smještaj polja ili matrice), potrebno je napisati vlastiti kopirajući konstruktor koji će pravilno kopirati cijeli objekt i dodatnu memoriju koju objekt zauzima. Npr. ako smo za jedan objekt zauzeli dodatnih 500 bajtova memorije (za koje postoji pokazivač koji na njih pokazuje), tada je u novom objektu također potrebno zauzeti jednaku količinu memorije i pridjeliti joj pokazivač novoga objekta. Ukoliko sami ne definiramo kop. konstruktor, prevodilac će kopirati samo objekt i tako dobiti dva objekta koji koriste isti memorijski prostor.
Kopirajući konstruktor kao parametre uzima referencu na objekt tipa vlastitog razreda koja može biti konstantna (const):

Razred::Razred(const Razred &izvor)    // kopirajuci konstuktor
{  this.x = izvor.x;
   this.y = izvor.y;
}

Destruktor
Destruktor je pripadna funkcija koja se izvršava kada objekt treba obrisati iz memorije (npr. prevodilac poziva destruktore za sve neuništene objekte na kraju rada programa). Destruktor se definira interno ako ga sami ne definiramo. Ukoliko naš razred koristi pokazivače ili reference, trebamo napisati vlastiti destruktor koji će osloboditi zauzetu memoriju tokom života objekta. Destruktor ima ime razreda sa znakom ~ na početku i za razliku od konstruktora ne prima parametre.
 
// destruktor
Razred::~Razred()
{    ...    }
 

Pridruženi razredi i funkcije
Upotrebom ključne riječi friend može se dopustiti nekom drugom razredu ili funkciji pristup do private ili protected članova razreda.

 class Razred
 {  friend class drugiRazred;
    friend void treciRazred::funkcija(int);
    friend void ObicnaFunkcija(double);
 };

Pristup možemo dopustiti svim funkcijama drugog razreda, samo nekim funkcijama razreda ili običnim (globalnim) funkcijama. Pridruživanje nije dvosmjerno; specifikatori pristupa nemaju utjecaja na pridružene razrede i funkcije.

Nadgradnja pripadnih funkcija
Pripadne funkcije (kao i obične) mogu se nadgraditi tako da imaju isto ime a liste parametara su im različite. Ovisno o navedenim parametrima u pozivu funkcije, prevodilac poziva odgovarajuću. U OOP često se nadgrađuju kostruktori.

 class Razred
 {
  Razred();       // prvi konstruktor
  Razred(int i);  // drugi konstruktor
 };
 
 ...
 Razred R1;       // poziva prvi konstruktor
 Razred R2(7);    // poziva drugi konstruktor
 

Nadgradnja operatora
Na objekte nekog razreda može se primjeniti većina standardnih operatora ukoliko ih nadgradimo - definiramo za određeni razred. Pri tome ostaju pravila udruživosti i prednosti operatora. Nadgrađeni operatori mogu se nasljeđivati.
Koristimo li aritmetiku operatora u rukovanju s objektima, vrlo često je potrebno nadgraditi operator pridruživanja ( = ) za definirani razred. Prevodilac generira pretpostavljeni operator pridruživanja ako ga mi samo ne definiramo, ali ako razred sadrži pokazivače tada pretpostavljeni operator pridruživanja nije adekvatan (jer će npr. pokazivači novog objekta pokazivati na istu memorijsku lokaciju kao i pokazivači izvornog, dok je u većini primjena potrebno zauzeti novu memoriju) - vidi pod kopirajući konstruktor.
Također je korisno da operator pridruživanja vraća referencu na objekt unutar koga se nalazi (referenca na this), čime se omogućava ulančano pridruživanje.
Primjer nadgradnje operatora:
 
class Double
{ private:
      double data;
  public:
      void Set(double _data)
      {   data=_data; }
      Double& operator= (const Double &izvor)
      {   data=izvor.data;
          return *this;
      }
      Double operator+ (const Double &pribrojnik)
      {   Double rezultat;
          rezultat.data=(*this).data+pribrojnik.data;
          return rezultat;
      }
};

int main(void)
{   Double a,b,c;
    a.Set(1);
    c=b=a;
    a=b+c;
}