C++ tutorijali... zaključana tema

poruka: 148
|
čitano: 117.975
|
moderatori: Lazarus Long, XXX-Man, vincimus
+/- sve poruke
ravni prikaz
starije poruke gore
17 godina
neaktivan
offline
RE: C++ tutorijali...
Quark kaže...

Još jedno pitanje o switch-string funkciji.

Shvatio sam da ona mora imat int u sebi,ali dali postoji način na koji bi se "zaobišlo" upisivanje broja.

 

npr:

 

#include<iostream>

#include<string>

 

using namespace std;

 

int main ()

{

string ime="ja";

int broj=1;

 

cout << "Unesite ime: ";

cin >> ime;

 

switch (broj)

{

case 1:

cout << "Ulogirani ste!";

break;

default:

cout << "Pogresno ime!";

}

system("PAUSE");

return 0;

}

 

 

Nelogično mi je da posle lozinke(ili bilo čega drugog) moram upisivat i broj(koji nema veza a unosom),dali postoji način da se taj broj poveže u inicijalizaciji sa stringom tako da kad se unese određeni string da se on(string) odmah poveže sa brojem(case 1,2...)?

Znam da se ovaj primjer može lakše napravit pomoću if-else funkcije,ali da li može i sa switchom?

 Pogledaj samo ovaj link u svezi switch() iskaza,inače je moguće i string uglaviti kao
switch() iskaz ali zahtijeva dva tri reda viška koda ili se može napisati u C++/CLI for Net
programu.Kad si dam truda napišem.

http://www.geekinterview.com/question_details/30963

v_maxcpp
17 godina
protjeran
offline
C++ tutorijali...

Evo malog primjera s predlošcima klasa:

 

#include <iostream.h>

template <class T>
class Polje
{
   public:
      T* polje;
      int BrojElemenata;

      Polje(int n);
      ~Polje() {delete[] polje;}
      int Sadrzi(T vrijednost);
};

template <class T> Polje<T>::Polje(int n)
{
   BrojElemenata = n;
   polje = new T[n];
}

template <class T> int Polje<T>::Sadrzi(T Vrijednost)
{
   int pom = 0;
   for(int i = 0; i < BrojElemenata; i++)
      if(polje[i] == Vrijednost)
         pom = 1;
   return pom;
}

int main()
{
        // kreiraj polje cijelih brojeva od 100 elemenata
   Polje <int> A(100);

        // inicijalizacije polja
   for(int i = 0; i < 100; i++)
      A.polje[i] = i;

        // da li se u polju nalazi broj 99?
   cout << A.Sadrzi(99);

        // koliki je broj elemenata
   cout << A.BrojElemenata;

   return 0;
}

 

U ovom slučaju varijabla A predstavlja int polje od 100 elemenata, ali za razliku od običnog polja možemo odmah doznati broj elemenata i da li se neka vrijednost nalazi u polju. Mogućnosti su bezbrojne i samo trebate smisliti i dodati neku novu funkcionalnost za rad s poljima, no to nikako ne bi bilo moguće da ne postoje predlošci funkcija i klasa. Ako ima kakvih pitanja... pitajte.


Poruka je uređivana zadnji put sri 2.7.2008 11:39 (Tracer).
Moj PC  
0 0 hvala 0
17 godina
neaktivan
offline
C++ tutorijali...

Svake pohvale onima koji su pisali sve ove tutove!

No, imam jedno pitanje. Mogu li se u Win32 CA programima pisati hrvatska slova? Vidio sam negdje da se moraju pisati ASCII znakovi, no ja ne znam kako  Neodlučan

 
0 0 hvala 0
17 godina
neaktivan
offline
RE: C++ tutorijali...

U ASCII/u nema hrvatskih znakova....
probaj sa wchar-om koji JA MISLIM koristi UTF-8....
ali prvo moras include-at <wchar.h> zaglavlje

16 godina
neaktivan
offline
C++ tutorijali...

Imam 1 lako pitanje (al meni je teško), kako napravit npr. pritiskom tipke "+" (mislim na onu iz tipkovnice) da se aktivira recimo button5?

 
0 0 hvala 0
17 godina
offline
RE: C++ tutorijali...

Kada stisneš neku tipku, poruka WM_KEYDOWN se pošalje kontroli koja ima keyboard fokus. Najlakše bi ti problem bilo riješit uporabom hooksa:

 

// Ovo staviš negdje na početku(npr. u init dialog(windows) procedure)

HHOOK hook=SetWindowsHookEx(WH_GETMESSAGE, KeyboardProc, hInstance, (DWORD)GetCurrentThreadId());

 

// Ovo staviš bilo gdje

// Ova procedura se pokrene kad god stisneš tipku a aplikacija ti je aktivna

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
// Ako je nCode negativan onda nesmijemo raditi ništa s porukom
// nCode zapravo ovisi o tipu hook-a ali uglavnom ovo gornje pravilo vrijedi.
if(nCode>=0)
    {
    //
    MSG *HookMsg;
    HookMsg=(MSG *)lParam;
    // Ako je poslana poruka WM_KEYDOWN tj. ako je stisnuta neka tipka i ako je wParam od
    // te poruke VK_ADD tj. ako je ta tipka baš +
    if(HookMsg->message==WM_KEYDOWN)
        {
        if(HookMsg->wParam==VK_ADD)
        {
            // Napravi ono šta radiš u buttonu
        }
       
        }
    }
return CallNextHookEx(0, nCode, wParam, lParam);
}

 

// Ovo staviš negdje di ti se zatvara aplikacija

UnhookWindowsHookEx(hook);

 

// NAPOMENA: varijabla hook mora biti globalna i funkcija KeyboardProc treba prototip najvjerovatnije

// Ako želiš baš aktivirati button možeš ovako:

SendMessage(HANDLE_WINDOWS_PROCEDURE, WM_COMMAND, MAKEWPARAM(ID_BUTTONA, BN_CLICKED), 0);

17 godina
neaktivan
offline
RE: C++ tutorijali...

class template  : malo o tome



Evo nakon poduže vremena .
Vidim da je kolega krenuo s template(predlošcima) klasa.Ja ću se samo nadovezati na temu i naravno svi mogu dodati ili me ispravljati!
Prije nego krenete s čitanjem u ovom postu molim ponovite (negdje na sredini) o predlošcima funkcja koje sam napisao ovdje na forumu
tj. na ovim tutovima.

Prvo općenito:
Sintaksa class tmplate je slijedeća:

template<class T> deklaracija
-pod onim deklaracija može stajati deklaracija klase ili funkcije,parametar T(ili argument T,ovisi kako tko piše) se zamjenjuje s stvarnim tipom koji
upotrebljavamo ili koji želimo u programu kasnije.
Znači ovom sintaksom smo stvorili predložak klase koju ćemo koristiti na slijedeći način:

naziv_predloška<tip>
ili :

predložak<argumenti> deklaracije
Naravno,sve između <> tih zagrada je naš tip T koji zamjenjujemo s onim tipom koji nam treba u programu.

Stoga sintaksa samo za jedan parametar je :

template<class T>
class ime_klase
{
    deklaracija
};

Naravno ,T se može koristiti i u deklaracijama s time da se zamjenjuje tipom koji odgovara trenutnom pozivu(int ili double ili naziv klase).
Evo samo jednostavan primjer kako napisati predložak:

template<class T>
class P
  {
      T a,b;
   };

...i sad da bi je koristili navodimo ime naše klase a to je P i u uglato-oštrim  zagradama navedemo tip umjesto T  :

   P<int>
   P<double>

...na taj način T je ili int ili double a sadrži znači a i b tog tipa.
To je bio samo početak o ovoj temi jer sad idemo malo kompliciranije .
Ovdje niže dolje je predložak klase koju ćemo upotrijebiti u glavnom programu nakon što malo i ovo objasnim
ali malo kasnije kad stignem:

template <class T> class CPrimjer

{
public:
    //konstruktori
    CPrimjer(const T vrijednosti[],int brojac);
    CPrimjer(const T& vrijednost);
    CPrimjer()
    {
        m_P=0;
    }
    bool Zbr(const T& vrijednost);
    T Max() const;
private:
    T m_Vrijednosti[100];
    int m_P;
};
//sad konstruktori
//______________________________________________
template <class T> CPrimjer<T>::CPrimjer(const T vrijednosti[],int brojac)
{
    m_P = brojac<100?brojac:100;
    for(int x = 0;x<m_P;x++)
        m_Vrijednosti[x] = vrijednosti[x];
}
//**********************************************

template <class T> CPrimjer<T>::CPrimjer(const T& vrijednost)
{
    m_Vrijednosti = vrijednost;
    m_P=1;
}
//______________________________________________
template<class T> bool CPrimjer<T>::Zbr(const T& vrijednost)
{
    bool OK = m_P < 100;
    if(OK)
        m_Vrijednost[m_P++] = vrijednost;
    return OK;
}
//********************************************

template<class T> T CPrimjer<T>::Max()const
{
    T tMax= m_P ?m_Vrijednosti[0] : 0;
    for(int x = 1; x<m_P;x++)
        if(m_Vrijednosti[x]>tMax)
            tMax =m_Vrijednosti[x];
    return tMax;
}
//_______________________________________________

 

Ali prije nego krenem u opsežno objašnjavanje gore navedenog primjera samo jednostavan program koji pokazuje najednostavniju primjenu
predloška klase gdje je vaša jedina dužnost da samo mijenjate tip koji se koristi kad formirate klase.Proučite ga i vidite sličnost
s predlošcima funkcija koje sam prije obradio:

#include <iostream>
using namespace std;
//OVDJE NAM JE JEDAN PREDLOŽAK KOJI ĆEMO KORISTIT ZA TRI TIPA KAO DA IMAMO TRI KLASE!
template<class T>
class Templ
{
public:
    T a,b ,c;


};
int main()
{
    Templ<int> klas;
    klas.a;
    Templ<double> bklas;
    bklas.a;
    Templ<float> cklas;
    cklas.a;
    return 0;
}
Sad recimo prvi primjer int tipa c++ prevodioc ovako to sebi prikaže:


class Templ<int>              //ovdje je <class T> znaci zamijenjeno
                              //s tipom int i imamo klasu s tipom int

{
    int a,b,c;
};

Sad vidite da po predlošku klase s početka programa(koda) prije int main() možemo napaviti klasu s tri različita tipa
a ne moramo je tri puta pisati!!!!Eto to je najjednostavniji prikaz kako se predložak klase može koristiti....nastavljamo s
kompliciranijim programom.Naravno ne kompliciram s objašnjenjem jer je bit da shvatite kako predložak sam po sebi ima svrhu.
Također ,predlošci klasa mogu imati i svoje parametre a njihov općeniti oblik je :

template <parametar,parametar......parametar> definicija(ili deklaracija) klase čiji predložak radimo

 


Znači ti parametri su forma koja se popunjava realnim argumentima u trenutku izvršavanja programa......parametri mogu biti
tipovi ugrađeni u c++ ili konstante.U programu kao i kod funkcija moramo poštivati sve navedene parametre.

Sad ćemo se vratiti malo na onaj kompliciraniji dio i naravno opet jedan uvod o predlošcima jer od viška glava ne boli.
(ali kad stignem).

class template -    nije samo po sebi klasa ,ona je više kao primatelj klase koju kada kompajler generira kod za klasu.
U primjeru koji slijedi želimo klasu (predložak) koja može primiti više podataka različite vrste da se tako izrazim.
A svaka klasa mora imati funkciju koja izračunava maksimalnu vrijednost iz podataka.
Na temelju toga što sam spomenuo mi ćemo napraviti predložak klase CPrimjer.
T nam je sve prisutan jer on je bitan pri kopajliranju i izvršavanju koda za različite klase koje će se koristiti našim ppredloškom.
Naravno ne zaboravite na prije spomenute ključne riječi i oblik kako se piše predložak!

Napominjem da ponovite prijenos po adresi i vrijednosti u na ovim stranicama prije ,jer se "tip" T mora zamijeniti sa stavrnom vrijednošću u programu da bi
mogli raditi s vrijednostima koje su stavrne.Ovo ćete razumjeti ako pročitate postove prije ovoga u tutorijalu.

 

template <class T> class CPrimjer

{
public:
    //konstruktori 
    CPrimjer(const T vrijednosti[],int brojac);  //deklaracija konstruktora koji prima "array" s podacima
    CPrimjer(const T& vrijednost);             //koji prima pojedinačnu vrijednost
    CPrimjer()                               //defaultni konstruktor(podupire stavranje praznog objekta-bez podataka)
    {
        m_P=0;
    }

//deklaracije funkcija

    bool Zbr(const T& vrijednost);
    T Max() const;
private:
    T m_Vrijednosti[100];     //"Array" za podatke
    int m_P;                   //pokazatelj (index ) za našu slobodnu lokaciju
};
//sad konstruktori
//i njihove definicije znači tijela
//______________________________________________
template <class T> CPrimjer<T>::CPrimjer(const T vrijednosti[],int brojac)
{
    m_P = brojac<100?brojac:100;
    for(int x = 0;x<m_P;x++)
        m_Vrijednosti[x] = vrijednosti[x];
}
//**********************************************

template <class T> CPrimjer<T>::CPrimjer(const T& vrijednost)
{
    m_Vrijednosti = vrijednost;
    m_P=1;
}
//______________________________________________
//ako je mjesto prazno stavi u njega vrijednost

template<class T> bool CPrimjer<T>::Zbr(const T& vrijednost)
{
    bool OK = m_P < 100;
    if(OK)
        m_Vrijednost[m_P++] = vrijednost;
    return OK;
}
//********************************************
//funkcija koja provherava sve vrijednosti i nalazi najveću!!!

template<class T> T CPrimjer<T>::Max()const
{
    T tMax= m_P ?m_Vrijednosti[0] : 0;
    for(int x = 1; x<m_P;x++)
        if(m_Vrijednosti[x]>tMax)
            tMax =m_Vrijednosti[x];
    return tMax;
}
//_______________________________________________


Ovo je znači predložak koji ćemo upotrijebiti za neke klase u programima koje se međusobno razlikuju po
tipovima podataka,broju podataka  ili uopće nemaju podataka...uviđate već sad prednosti predloška klasa?
Ne moramo pisati svaki put novu klasu s tipom koji nam treba za izračun ...imamo predložak i njega koristimo
s različitim klasama tj.njega koriste različite klase.Sad kad ste sve ovo dosad proučili možemo i dalje.
Ja se trudim ne komplicirati previše jer želja mi je shvatiti bit predloška klase ,a sama upotrebljivost koda ide na vašu odgovornost.
Naravno ispričavam se i znalcima c++-a ako isuviše pojednostavljujem.
Svi ste tu i da me ispravite i dopunite......
Prelazimo na glavni program u kojem ćemo i upotrijebiti naš predložak klase(ali kasnije opet):

___________________________________________________________________________

Mala samo digresija:
Stvaranje objekta iz class template

Da bi kreirali objekat baziran na predlošku klase morate uvijek navesti tip između <> koji naravno slijedi nakon imena klase.


CPrimjer<double>moji_podaci(24.9);

Znači ovako stavramo objekat tipa double ,moji_podaci,u koji sad možemo spremiti vrijednost tipa double.

____________________________________________________________________________

 

Sad naravno čitav program pa dio po dio objasnim,naravno možete ga i vi sami proučavati
i ako ste dosad sve lijepo pratili ne bi vam trebalo biti teško razumjeti .
Evo kod:

 

 

#include<iostream>
using namespace std;

class CKutija
{
public:
    //Definicija kostruktora
    CKutija(double v = 1.0,double s = 1.0,double d = 1.0):visina(v)
    {
        duzina = d > s ? d: s;
        sirina = s < d ? s : d;
    }
    double Volumen() const
    {
        return duzina * visina * sirina;
    }
    int CKutija::operator>(const CKutija &aKutija)const
    {
        return this->Volumen() > aKutija.Volumen();

    }
    int operator>(const double &vrijednost)const
    {
        return Volumen()> vrijednost;
    }
    CKutija operator+(const CKutija &aKutija)const
    {
        return CKutija(duzina > aKutija.duzina?duzina:aKutija.duzina,
            sirina > aKutija.sirina?sirina:aKutija.sirina,
            visina + aKutija.visina);
    }
    void PokaziKutiju() const
    {
        cout<<duzina<<" "
            <<sirina<<" "
            <<visina<<endl;
    }


private:
    double sirina;
    double visina;
    double duzina;
    };
int operator>(const double &vrijednost,const CKutija &aKutija);
//**********************************************************
template <class T> class CPrimjer

{
public:
    //konstruktori samo njihove deklaracije
    CPrimjer(const T vrijednosti[],int brojac);
    CPrimjer(const T& vrijednost);
    CPrimjer()
    {
        m_P=0;
    }
    bool Zbr(const T& vrijednost);
    T Max() const;
private:
    T m_Vrijednosti[100];
    int m_P;
};
//sad konstruktori i funkcije i njhove definicije i ponovite
//ranije u tutorijalu razdvajanje definicije i deklaracije 
//______________________________________________
template <class T> CPrimjer<T>::CPrimjer(const T vrijednosti[],int brojac)
{
    m_P = brojac<100?brojac:100;
    for(int x = 0;x<m_P;x++)
        m_Vrijednosti[x] = vrijednosti[x];
}
//**********************************************

template <class T> CPrimjer<T>::CPrimjer(const T& vrijednost)
{
    m_Vrijednosti = vrijednost;
    m_P=1;
}
//______________________________________________
template<class T> bool CPrimjer<T>::Zbr(const T& vrijednost)
{
    bool OK = m_P < 100;
    if(OK)
        m_Vrijednost[m_P++] = vrijednost;
    return OK;
}
//********************************************

template<class T> T CPrimjer<T>::Max()const   
{
    T tMax= m_P ?m_Vrijednosti[0] : 0;
    for(int x = 1; x<m_P;x++)
        if(m_Vrijednosti[x]>tMax)
            tMax =m_Vrijednosti[x];
    return tMax;
}
//_______________________________________________



int main()
{
    //OVDJE KORISTIMO SAMO KLASU CKutija
    CKutija mala(4.0,2.0,1.0);
    CKutija srednja(10.0,4.0,3.0);
    CKutija aKutija;
    CKutija bKutija;

    aKutija = mala + srednja;
    cout<<"Velicina aKutije je : ";
    aKutija.PokaziKutiju();

    bKutija  = aKutija + mala + srednja ;
    cout<<"bKutija je velika  : ";
    bKutija.PokaziKutiju();
    //TEK SAD U OVOM KODU ISPOD KORISTIMO PREDLOZAK KLASE
    cout<<"**********************************************"<<endl;
CKutija kutije[] =
{
    CKutija(7.0,4.8,3.0),
    CKutija(5.8,4.0,3.0),
    CKutija (3.0,5.0,3.0)
};
CPrimjer<CKutija> mojeKutije(kutije,sizeof kutije/sizeof CKutija);
CKutija najKutija = mojeKutije.Max();
cout<<"Najveca od kutija ima volumen : ";
cout<<najKutija.Volumen()<<endl;
    return 0;
}

Čitav ovaj kod je pisan u Visual Studiu kao Empty Project i Add cpp file na source file u Solution Exploreru....ako kome ovo nije jasno objasnim kako raditi u VS-u
iz praznog projekta.
Kod izvršavanja programa ,kompajler kreira instancu predloška za funkciju koju mi pozivamo u programu ..a to je naravno Max() funkcija.
U biti mislim da sam dosta rekao o predlošcima klasa i na vama je samo da dio po dio koda analizirate i ako ste dosad
prošli sve u tutorijalu ,neće vam biti teško ovdje sve dio po dio prolaziti.Sami prođite redak po redak koda i sve vam mora biti jasno.
Samo upornim ponavljanjem i pisanjem koda možete svladati C++ ili bilo koji drugi programski jezik.To znači puno sati vježbanja i učenja.
Ako pri prvom prolasku ne razumjete pojedine dijelove ,samo upornim vježbanjem čete i to svladati,nisam ni ja drugačije učio.
Naravno ,ako baš zapnete ima autora na ovom tutu koji osim mene mogu pomoći a vjerujem i na ovom forumu.
______________________________________________________________________________________________________



 

 

 

 

 

 

v_maxcpp
Poruka je uređivana zadnji put čet 31.7.2008 22:39 (v_maxcpp).
17 godina
offline
RE: C++ tutorijali...
v_maxcpp kaže...

Sad možemo prijeći na rekurzivne funkcije.
Rekurzivna funkcija je u biti funkcija koja samu sebe poziva više puta->doslovno prevedeno.Slijedi program ali to sutra......

A sutra je došlo....

/*u ovom programu vidimo tkz.uzastopno pozivanje unutar
funkcije i to se zove rekurzija.Unutar same funkcije mi stavaramo
lokalne varijable koje je moguce samo koristiti unutar
te funkcije i to nam omogucava da mozemo jednu te istu funkciju
pozivati koliko hocemo puta unutar same funkcije i to se
zove rekurzija,naravno svako pozivanje i rezultati se spremaju u memoriju
na "stog" i treba paziti da se ne prepuni sama petlja i stoga nam
funkcije s rekurzijama odgovaraju ssamo pri nekim rjesenjima tj. upravljanjem
strukturama podataka,a otome opet ukasnijim izlaganjima*/


#include <cstdlib>
#include <iostream>
using namespace std;
double funk_racun(double x,int n);
int main()
{
    double x = 3.0;
    double rezultat = 0.0;
    for(int pokazatelj = -3;pokazatelj<=3;pokazatelj++)        //ponovite for petlju
    {
      cout<<x<<"\t izracun  "<<pokazatelj<<" je "
      <<funk_racun(x,pokazatelj)
      <<endl<<endl;
      }  
    system("PAUSE");
    return 0;
}
double funk_racun(double x,int n)              //unutar funkcije dva tipa koja pošticamo u programu
{
  if(n<0)                                //ponovite if-else
  {
    x=1.0/x;
    n= -n;
  }
  if(n>0)
  {
  return x*funk_racun(x,n-1);
  }
  else
  return 1.0;
}


Prvo svaka cast na trudu v_maxcpp.

 

Poceo sam pratiti ove tutoriale i zapeo sam na gornjem primjeru (rekurzivne funkcije, strana 2)

Ono sto shvacam je slijedece :

 

u main funkciji vrtimo for petlju od -3 do 3 za pokazatelj, i u svakom koraku ispisemo X (originalni!!!), zatim text pa pokazatelj (-3....3) te na kraju pozivamo rezultat funkcije funk_racun.

 

U funkciji funk_racun, sa prvim IF-om smo se osigurali da nam pokazatelj bude uvijek pozitivna vrijednost (osim u slucaju nule, kada funk_racun vraca 1....else....return 1), a sa drugim IF uvijetom smo osigurali da je pokazatelj veci od nule (opet ako je nula, vraca 1).

 

E sad, nemogu skontat samu akciju koju funkcija provodi na argumentima koje prima.

 

    return x*funk_racun(x,n-1);

 

Uzme x (3 ili 0,33333, ovisi kojeg je predznaka pokazatelj) i pomnozi ga sa funk_racun(x,n-1)......?!?!?! opet pozivamo funkciju, a nigdje ne pise sta ona ustvari radi.

 

Primjer je valjan, jer dobivam tocne rezultate, al ja ne kontam (arghhhhh).

 

Moze malo objasnjenje.....ipak sam noob (james noob)Cool

17 godina
neaktivan
offline
RE: C++ tutorijali...


//evo sam taj primjer tj. rekruzivnu funkciju objasnti ću na primjeru Fibonaccijevog niza
/*  FIBONACCI NIZ*/
/*To je niz brojeva kod kojih je svaki slijedeći broj u nizui jedank zbroju dvaju prethodnih:
      0,1,1,2,3,5,8,13......idt:
   Opća formula je :   F(n+1) = F(n) + F(n-1)
   ili :
   F(i) = F(i-1) + F(i-2) ...sve to je već davno napisano...samo ponavljam */  
 //************************************************************************


   #include <iostream>
   using namespace std;
   long fibonacci(long);
   int main()
   {
       //Ovdje postavljamo da zelimo niz od deset fibonacci brojeva
       for(int brojac =0;brojac<=10;brojac++)
       cout<<"Fibonacci ("<< brojac << ") ="
       <<fibonacci(brojac)<<endl;
      // cout<<"Fibonacci (11) :" <<fibonacci(11)<<endl;//ovo u zagradi je jedanaesti zbroj znači i dalje smo je pozvali
        //cout<<"Fibonacci (30) :" <<fibonacci(30)<<endl;//ovo je trideseti zbroj
       system("pause");
       return 0;
       }
       long fibonacci(long broj)
       {
            if((broj == 0) || (broj == 1))
            return broj;
            else
            return fibonacci(broj -1)+ fibonacci(broj -2);
            }
                                 
//znaci mi smo sad prikazali niz od deset fibonacci brojeva
//pomoću for petlje smo je pozvali deset puta da nam to izračuna
//u if uvjetu nam je ako je nula pocni s nulom a tako i s jedinicom(vrati broj)
//to ti je kad kompajlaš ona prva dva broja
//dalje se primjenjuje iza else uvjeta sve,znači (2-1) + (2-2) = 1
//tako dobiješ 0,1,1
//dalje probaj sam.....(3-1) + (3-2) = 3....itd i tako deset puta pozivaš funkciju
//znači unutar for petlje ona samu sebe poziva deset puta.
//znači rekurzivna funkcija dok se ne ispuni for petlja uvjet.

//zbriši komentare s fibonacci(30)

//sad vidiš logiku rekurzivne funkcije

//još koji program napišem za rekruzivnu funkciju.

Ako još nije jasno javi jer na sličnom principu radi i kod funkcije koji si naveo u pitanju samo ima više redaka ali princip je isti.

#include <cstdlib>
#include <iostream>
using namespace std;
double funk_racun(double x,int n);
int main()
{
    double x = 2.0;
    
    for(int pokazatelj = 0;pokazatelj<=3;pokazatelj++) //ovdje sam uveo samo pozitivne brojeve      
    {
      cout<<x<<"\t na  "<<pokazatelj<<" je "
      <<funk_racun(x,pokazatelj)// ,a ispis takav zbog petlje koja
      //kreće od nule (to je int n ).
      <<endl<<endl;
      }  
    system("PAUSE");
    return 0;
}
double funk_racun(double x,int n)              //unutar funkcije dva tipa koja pošticamo u programu
{
  if(n<0)                                //ponovite if-else
  {
    x=1.0/x;
    n= -n;
  }
  if(n>0)
  {
  return x * funk_racun(x,n-1);// x je stalno tri a n je pokazatelj
  }
  else
  return 1.0;
}
//....zatim ako je n>0 a to je tri oduzmi jedan i to je dva na drugu
//pa onda dva na prvu i na kraju dva na nulu.Ali petlja je do tri i tako i na treću
//u for petlji možeš napisati i umjesto tri  broj četiri pa dobiješ dva na četvrtu i tako dalje......
//ono n-1 je zato da bi došla do kraja.

Malo sam izmjenio kod  pa probaj sad sve ponoviti i točno mi reci koji baš dio ne razumiješ
ili baš funkciju ne razumiješ pa ću ponoviti još detaljnije sve kad budem imao više vremena.
Dva if uvjeta su samo zato da nam kažu ako je negativan idi tako ,a ako je pozitivan idi opet ....

Sad u ovom kodu koji sam ti dao probaj ovo:

/*if(n<0)                                //ponovite if-else
  {
    x=1.0/x;
    n= -n;
  }*/

Znači staviti komentar,ali sad možeš samo pozitivne brojeve pisati!


Evo značenje n-1......opet sam malo promijenio kod da vidiš što znači n-1......a one nule je zato što sam izostavio x i nema množenja!(pogledaj ispis i usporedi)

#include <cstdlib>
#include <iostream>
using namespace std;
double funk_racun(int n);  //ovdje sam izvršio promjene
int main()
{
    double x = 2.0;
    
    for(int pokazatelj = 0;pokazatelj<=3;pokazatelj++) //ovdje sam uveo samo pozitivne brojeve      
    {
      cout<<x<<"\t na  "<<pokazatelj<<" je "
      <<funk_racun(pokazatelj)// ,a ispis takav zbog petlje koja
      //kreće od nule (to je int n ).
      <<endl<<endl;
      }  
    system("PAUSE");
    return 0;
}
double funk_racun(int n)              //unutar funkcije dva tipa koja pošticamo u programu
{
       double x;
  /*if(n<0)                                //ponovite if-else
  {
    x=1.0/x;
    n= -n;
  }*/
  if(n>0)
  {
  return x * funk_racun(n-1);// x je stalno tri a n je pokazatelj
  }
else
  return 1.0;
}

Eto ,još budem ako treba.

 

 

 

 

 

v_maxcpp
Poruka je uređivana zadnji put sub 2.8.2008 18:05 (v_maxcpp).
17 godina
offline
C++ tutorijali...

Fibonacci-ja kuzim, barem mislim.... Smijeh

 

ali ove druge ne..... Tocno ne kuzim ovu liniju :

 

return X * funk_racun(x,n-1)

 

ne vidim nikakvu matematicku operaciju koju funkcija vrsi (samo jedan od argumenata smanji za 1-----n-1)

 

evo po koracima:

 

--------pokazatelj=0  rezultat=1 (zbog else return 1)........ ok, to kuzim

 

--------pokazatelj=1    return 2*funk_racun(2,0).....kako ovo moze dati rezultat 2 ?!?

 

--------pokazatelj=2    return 2*funk_racun(2,1)......4 ?!?

 

--------pokazatelj=3    return 2*funk_racun(2,2)......8  ?!?

 


kako vidim po rezultatima funkcija funk_racun racuna X^n, ali to se nigdje ne vidi, barem ja ne mogu uociti.....

 

 

What Would Biran Boitano Do?
 
0 0 hvala 0
17 godina
neaktivan
offline
RE: C++ tutorijali...
noob007 kaže...

Fibonacci-ja kuzim, barem mislim.... Smijeh

 

ali ove druge ne..... Tocno ne kuzim ovu liniju :

 

return X * funk_racun(x,n-1)

 

ne vidim nikakvu matematicku operaciju koju funkcija vrsi (samo jedan od argumenata smanji za 1-----n-1)

 

evo po koracima:

 

--------pokazatelj=0  rezultat=1 (zbog else return 1)........ ok, to kuzim

 

--------pokazatelj=1    return 2*funk_racun(2,0).....kako ovo moze dati rezultat 2 ?!?

 

--------pokazatelj=2    return 2*funk_racun(2,1)......4 ?!?

 

--------pokazatelj=3    return 2*funk_racun(2,2)......8  ?!?

 


kako vidim po rezultatima funkcija funk_racun racuna X^n, ali to se nigdje ne vidi, barem ja ne mogu uociti.....

 

 

 ovako:
2 na prvu je dva
2 na 2 = 4:
2 na 3 = 8:
To je u biti to.
Napisao si funk_racun(x,n-1) kao funk_racun(2,0)...itd.....a  radi se samo o nuli a ne o (x,nula) jer to je samo oblik funkcije koju pozivaš
Ti u biti množiš 2 s n-1 .
Evo malo pojednostavljeno...

#include <iostream>

using namespace std;
int funkcija(int x,int n);

int main()
{
    int x=2;
    int n;
    cout<<"X je broj dva"<<endl;
cout<<"Unesite n : " <<endl;
  cin>>n;
   cout<<endl;
   
   
   cout<<"X na n-1 je :"<<funkcija(x,n);
   
   cout<<endl;
   
    
    system("PAUSE");
    return 0;
}
int funkcija(int x,int n)
{
    
    cout<<n<<" ";//ispiši trenutnu vrijednost koju uneseš
    cout<<endl;
    if (n==1)  //ovo je uvjet završetka rekurzije
    return 1;
    else
    return x*funkcija(x,n-1); //pozivaš funkciju za n-1 ali množiš s x   (ponovo pozovi)
    cout<<endl;
     //ponovno zvanje funkcije s argumentom n-1
}

...pzivaš funkciju ali množiš s n-1!
Tako i u onom kodu ,množiš samo s n-1.
Kod funkcija da bi se pozivale moraju biti poštivani parametri s argumentima .
Napravim post samo s detaljnim objašnjenjem rekurzije.

Sutra ili kad budem uhvatio vremena napravim jedan te isti program za izračun faktorijela
...sa rekurzijom i bez nje a istim rezultatima....tada će biti sve puno jasnije s rekurzijom.
Evo pokušati ću s faktorijel od nenegativnih brojeva(pozitivnih)
Factorial
___________________________________________
unsigned long
pokriva samo pozitivne brojeve i zato smo
uzelli taj tip jer nam treba zbog samog faktorijela.
Ispričajte me ako pogriješim u izgovoru faktorijel ili faktorijal.
ako imamo samo long int tad pokrivamo od -2147483648 do 214783647
a unsigned long int  od 0 do 4294967295...samo u pozitivnom dijelu.
_______________________________________________________


#include <iostream>
#include<iomanip>                //zbog setw()
using namespace std;
unsigned long factorial(unsigned long);
int main()
{
    //faktorial od 0 do 10
    for(int y =0;y<=10;y++)
    cout<<setw(2)<<y <<" : "<<factorial(y)<<endl; //znaci ovje funkcija se vrti za svekai broj
    //ako je tri naprimjer tad ide zbog n-1 ....3*(3-1)*(3-2)=6
    //i tako sve do deset
 
    system("PAUSE");
    return 0;
}
unsigned long factorial(unsigned long  x)
{
         if(x<=1)     //uvjet  koji također kaže dok ne dođes do jedan
         return 1;
         else         // ovo je korak rekurzije
         return x*factorial(x-1);   pomnoži x s x-1 i pozivaj dok ne ispunis prvi uvjet!
 }
 
//***********************************************************
/*Sama rekurzija se izvršava od :
     10!
     10=9!
     9 =8!...i tako do
     1
     a povrat(rekurzija)
     ako je jedan vrati
     ako je dva vrati u funkciju i pmnoži s slijedećim
     sad se poveća za jedan i opet vrati u funkciju
     i tako do 10.
     To je zbog petlje koja kreće od jedan tj od nule.
     znači ako je nula tad je jedan
     ako je jedan = jedan;
     sad taj jedan return i
     2*1 = 1*2 = 2;
     sad taj dva return;
     3= 3*2 = 6
     sad taj 6 return;
     4*6 = 24
     sad taj 24 return;
     5 * 24 = 120
     i tako do deset kako piše u petlji.
 Rkurzivne funkcije su funkcije koje uvijek imaju neki uvjet .
 Sad sve ponovite dio po dio i nadam se da je bar malo jasnije što se tiče
 rekurzije.*/
    

A u ovom programu to isto ali samo kroz petlju pa usporedite i vježbajte ...
Kroz ova dva primjera se vide razlike zašto je jedno rekurzija a drugo "obična petlja"
i zašto se funkcija poziva samu sebe .....

#include <iostream>
#include<iomanip>                //zbog setw()
using namespace std;
unsigned long factorial(unsigned long);
int main()
{
    //faktorial od 0 do 10
    for(int y =0;y<=10;y++)
    cout<<setw(2)<<y <<" : "<<factorial(y)<<endl;    
    system("PAUSE");
    return 0;
}
unsigned long factorial(unsigned long  x)
{
        unsigned long rezultat=1;
        for(unsigned long a= x;a>=1;a--)   //do se ne dođe do jedan a ovdje ne poziva samu sebe
        rezultat = rezultat * a;          //vec je u petlji koja se vrti do jedan
        return rezultat;
        }
        
  //Znači općenita formula faktorijala je:
    //    n * (n-1) * (n-2)....1
      //  tj.
        //faktorijal od 5=5*(5-1)*(5-2)*(5-3)....i tako do kraja =120 je rezultat za faktorijal od 5!      



Ako što ne razumijete u ovi sad primjerima javite...razložiču ga na dijelove dijelova...









v_maxcpp
Poruka je uređivana zadnji put ned 3.8.2008 9:49 (v_maxcpp).
17 godina
offline
C++ tutorijali...

Ok, puno hvala na odgovoru.....

Stvari su sada nesto jasnije...

What Would Biran Boitano Do?
 
0 0 hvala 0
17 godina
neaktivan
offline
RE: C++ tutorijali...

....ako zapneš bilo gdje pošalji problem(postaj) i pokušat ću odgovoriti...naravno kad imam vremena....
...nadam se da nečeš odustati.

v_maxcpp
17 godina
neaktivan
offline
C++ tutorijali...

E, samo jedan detalj... Pisanje takvih stvari nizova rekurzivnom metodom je jako puno sporije od koristenja for petlje ili memoizacije....

Problem je znaci sta se funkcije sa istim parametrima vise puta zovu.... znaci, isti se procesi odvijaju vise puta, sta naravno nije dobro...
Evo, uzmimo npr fibbonaci(5). On zove fib(4) i fib(3).... fib(4) zove fib(3) i fib (2) zaci to je vec sada jedno ponavljanje iste funkcije

                                                                                                                                                              fib (5)
                        fib (4)                                       fib (3)

          fib (3)                     fib (2)               fib (1)           fib (2)
fib (2)            fib (1)            fib (1)                                 fib (1)      
fib (1)

Znaci, za N=5, fib (5) se racuna jednom, fib (4) isto, fib (3) 2 puta, fib (2) 3 puta, fib (1) 5 puta.... znaci, za N=5, bezveze radite 7 istih racuna....
Kako to rjesiti? Ili koristite for petlje umjesto rekurzije, sta ponekada nema smisla ili je jednostavno pretesko, ili koristite memoizaciju...
To je jako jednostavna metoda.... Pises sva rjesenja u array, i ako je rjesenje vec rjeseno, samo mu baci rjesenje iz arraya, a ne racunas ponovno....

Evo fib niz, sa memoizacijom

#include <iostream>
#include <cstring> //za gcc kompajlere verzije 4.0+ potrebno da bi radila funkcija memset

#define MAXN 50 //ovo sam postavio samo na 50 jer sam negdje procitao da za vece brojeve ne stane u long long int....
unsigned long long int memo[MAXN];
unsigned long long int fib (int);

int main (int argc, char **argv) {
     memset (memo, 0, sizeof(memo)); //postavlja sve elemente niza memo na 0
    
     if (argc != 1) {  //ako broj argumenata programu nije jednak 1 napisi mu upute
          cout << "Program koristi OVAKO:"  << endl;
          cout << argv[0] << "  n" << endl;  // argv[0] baca ime programa
          cout << "Gdje je n clan fibonacijevog niza kojeg zelite dobit (int manji od " << MAXN << ")" << endl;

          return 1; // izadji sa greskom
     }
     
     int n;

     sscanf (argv[1], "%d", &n); //pretvara char * u int te pise u varijablu n.... to sam vec objasnio u jednom tutorialu u ovom topicu
     if (n > MAXN) {
          cout << "Preveliko! Ne stane u int... sta mislis da mi se pise bignum varijanta??? Koristi brojeve manje od" << MAXN << endl;
          return 2; //izadji sa greskom
     }
     cout << n << "-ti clan fibbonacijevog niza je << fib (n) << endl;
     return 0;
}

long long int fib (int n) {
       if (n <= 1) return 1;
       if (memo[n] != 0) return memo[n];
       return memo[n] = fib(n-1) + fib (n-2); // postavi memo[n] i vrati tu vrjednost
}

Memoizaciju koristite UVIJEK kada i rekurziju.... jer i cak kada ne treba, zauzima jako malo memorije (u ovom primjeru, 50 int vrjednosti, a int je ja mislim 4 bajta). Inace ubrzava jakooo puno...
Nadam se da kopcate.... ako nis vise, naucili ste kako uzimati argumente prosljedjene programu..... ako imate pitanja recite....

Moj vam je savjet da si sada napisete BIGNUM varijantu ovoga (rekurzivno).... BUGNUMovi su brojevi toliko veliki da se pisu u znakovni niz....  I koristite obavezno char * (a ne string) tako da se lijepo naucite pointerima.... :)

Poruka je uređivana zadnji put ned 3.8.2008 22:48 (Jazzfan).
 
0 0 hvala 0
17 godina
protjeran
offline
C++ tutorijali...

Rekurzija se izvršava duplo više puta nego programska petlja. Razlog je u tome što svaki put kad se rekurzija izvrši međustanja tog poziva se stavljaju na Stog, a zatim kad dođe kraj izvršavanja onda se ta međustanja počinju skidati sa Stog-a. Kolega je to prethodno dobro demonstrirao primjerom.

 

U pravilu, rekurzijom se dobije kraći programski kod, ali optimizacija algoritma je u najčešćem slučaju loša, a pogotovo zbog njegove asimptotske složenosti. Isto tako, svaka rekurzija se može pretvoriti u ne-rekurziju i obrnuto, a za to treba slijediti čak 13 striktnih pravila ;)

Moj PC  
0 0 hvala 0
16 godina
neaktivan
offline
C++ tutorijali...

tutorijali su super poceo sam se baviti c++ stoga da mi ovo pomaze odlicno..hvala

Moj PC  
0 0 hvala 0
17 godina
neaktivan
offline
RE: C++ tutorijali...

Dosad svaka čast svima koji su se pridružili  u pisanju ovih tutorijala jer  vrijeme je dragocjeno i svaki napisani tut je veliki trud i znanje od svakoga za sve one koji počinju učiti c++.
Ja jednostavno mogu samo reći hvala jer dobra volja i želja za pomoći je u svima koji ste se pridružili.
Što se tiče tuta još ima par postova koje bi želio staviti.
Uporedo s njima kad budem imao vremena pisati ću i C++/CLI .Net okruženju ali uglavnom početke ....
Ovi tutorijali po mom mišljenju pružaju dobar uvid u C++ ili bar pružaju uvid u njega da bi mogli shvatiti sintaksu, i dalje možete
sami jer ako ste ih dobro prošli tad ste počeli razumijevati c++.
Što se tiče  C++/CLI je proširenje ISO/ANSI C++ jezika i uključuje .Net okruženje i stoga da bi učili u tom obliku
morate koristiti VS 2005 Express Edition minimalno koji je besplatan.Još jednom hvala savim autorima!

v_maxcpp
17 godina
neaktivan
offline
RE: C++ tutorijali...

hvala tebi... pa ti si najvise napisao ;)

e, da i predlazem da netko napravi novi topic, i copy-pasta samo tutoriale po nekom redu... kada je gotov,  neka obavjesti admine, koji stavljaju lock i sticky.... jer ovako je prenatrpano, prerazbacano.... mogu to ja napravit, ali bi radje da netko drugi, jer ja bas suxam u objasnjavanju, predavanju, ucenju i sl....

17 godina
neaktivan
offline
RE: C++ tutorijali...

 





friend class


Evo kao što je i u naslovu  dotaknut ću se friend class deklaracije...što znači da čitavu klasu
možemo proglasiti kao prijatelja klase i na taj način joj omogućavamo pristup podacima koji se nalaze u klasi
koja nam je prijatelj.Lakše ćete kroz primjer naučiti a naravno s ovim postom ću početi i govoriti(pisati) o samom
pojmu polimorfizma u C++-u koji obuhvaća virtulane funkcije i abstraktne klase.naravno da bi posve razumjeli
ono o čemu ću pisati molim ponovite sve dosad što sam napisao o klasama i OOP u C++-u na ovim stranicama.

Ali prvo friend class kao jedna mala ali bitna digresija:

#include <iostream>
using namespace std;

class A
{
  int a, b;
  friend class B;       //ovdje  deklariramo prijatelj klasu
public:
  A() : a(5), b(10) { }//konstruktor

};

class B           //naravno a ovdje je definicija te prijatelj klase
{
public:
  void ispisi(A& x) {
      cout << "a je :" << x.a << endl;            //pristupamo clanovima klase A jer smo prijatelji
    cout << "b je : " << x.b << endl;
  }

};

int main()
{
  A xobj;
  B friend_obj;
  friend_obj.ispisi(xobj);
  return 0;
}
//Mozete deklarirati cijelu klasu kao prijatelja.
//Ovdje smo nacinili da je klasa B prijatelj klase A.
//To znaci da svaki clan funkcije i staticka varijabla definicije u B klasi
//ima pristup podacima u A klasi.
//
//U ovom primjeru to su  svi clanovi B klase,
// friend class B ima clanicu funkciju ispisi koja pristupa privatnim clanovima a i b
//od class A

//znaci da ide prvo deklaracija nase prijatelj klase i onda definicija

Primjetite da nisam naveo private:   dio u klasi A jer ako ne navedete ništa po defaultu je private.
To svakako napominjem i to upamtite jer kad se radi o naslijeđivanju među klasama ,vrlo je bitno
što će klasa naslijediti,kao public ili private dio od osnovne klase ali o tome kasnije.
Sad malo proučavajte ovaj primjer pa ćemo na slijedeći i naravno zaključak o friend class.
Eto to će biti u ovom postu.
Da nastavimo,vidim i zahvaljujem kolegi Tracer-u jer nije sve ograničeno na klase nego i na funkcije
kao prijatelje ,posvetiti ću i tome par redaka na kraju.
Sad u ovom primjeru koji možete nadovezati na ovaj primjer prije a i na primjer niže od kolege :

#include <iostream>
using namespace std;

class A;        //obvezatno deklaracije klasa prije definicije

class B {       //također samo deklaracija
public:
  void ispis(A& x);
};
// i sad slijede definicije u kojima sve kombiniramo
class A {
  int a, b;
  friend void B::ispis(A& x);    //a ovdje smo znači samo funkciju proglasili prijateljem i naravno naveli iz koje klase
public:
  A() : a(5), b(10) { }
};

void B::ispis(A& x) {
    cout << "a je : " << x.a << endl;   //ovdje je definicija funkcije ispis, i naravno :: te dvotočke nam govore kojoj klasi
    cout << "b is : "<< x.b << endl;     //funkcija pripada  !!!!!!!!! :: dvotočke su mjesto razriješenja ovlasti (pripadnosti)!
}

int main() {
  A x_obj;
  B b_obj;
  b_obj.ispis(x_obj);
}

 

Vidite da je definicija funkcije van svih klasa i njihovih definicija ali je funkcija pripadnik
klase B i tu smo funkciju prograsili kao prijatelj klase A i omogućili pristup članovima klase A
Znači samo funkcija  koja pripada klasi B ima pristup članovima klase A.
Nisam navodio private: jer sam prije rekao razlog i naravno nisam napisao system("pause") jer radim u VS-u.
Vi to dodajte ako radite u Dev-u.
Prijateljstvo se ne naslijeđuje!Ako je neka funkcija prijatelj klase A ,a klasa C je izvedena iz klase A
tad ta funkcija(nekog imena) nije prijatelj te klase C osim ako vi unutar klase C ne upotrijebite friend deklaraciju.

 

Ako je klasa B prijatelj klasi A,a klasa C  prijatelj klasi B,tad klasa C nije automatski prijatelj klasi A.
Vi opet to morate navesti unutar klase deklaracijom friend ako to želite,ovo znači da se prijateljsto automatski ne prenosi
na klasu a nema veze s naslijeđivanjem.
Ako se radi i o naslijeđivanju opet vrijedi da se prijateljstvo ne naslijeđuje!!!!
Same funkcije koje su prijatelji neke klase mogu biti i globalne a ne pripadnice neke klase!
Sad malo proučavajte.

 

 

___________________________________________________________________________

 

virtual function

Virtualne Funkcije


Evo kako i sam naslov govori počinjem s virtualnim funkcijama ali prvo ćemo
napraviti jedan program koji sadrzi klasu iz koje smo napravili drugu klasu koja je naslijedila prvu klasu.
Prva klasa je tkz "Base class" a druga klasa je  "Derived class".....znači bazna klasa i ona koja je izvedena iz nje.
Koristiti će funkciju iz bazne klase.......to ćemo pokazati u ovom primjeru koji slijedi.
Sad ,kad vi želite da klasa ima funkciju iz bazne klase imenom PokaziVolumen a zelite da
derived class ima istu funkciju s istim imenom a različitom funkcijom kad je pozovete što znači
da pozivate kao da pozivate PokaziVolumen iz prve klase (Base) a ona se izvršava na novi način tj.
na način koji ste joj odredili u Derived class tad morate primjeniti klučnu riječ virtual .
Takav način pisanja funkcije tj. taj mali fenomen se zove polimorfizam  naravno to je
dio OOP c++-a!
Ovo sve ćete bolje razumjeti kroz programe koji slijede i naravno još objašnjenja.To sam samo dodirnuo
ukratko i kad budete čitali i kombinirali s programima i uporno vježbali vidjeti ćete da je lagano.

Ja sam radio u VS-u i princip je isti kao i kod Dev-a.Stvarate heder file-ove i cpp-filove i na kraju glavni(main) file
u kojem izvršavate program.Ako budete izrazili želju da vam detaljno sve prikazem slikama korsk po korak
to mi recite tj. pošaljite odgovor o toj želji:

Sad prvo Kutija.h:

#pragma once

class CKutija
{
public:
    CKutija(double,double,double);
    ~CKutija(void);
    void PokaziVolumen(void)const;
    double Volumen(void)const;
protected:
    double Duzina;
    double Visina;
    double Sirina;
};

Zatim Kutija.cpp

 

#include <iostream>
using namespace std;
CKutija::CKutija(double v=1.0,double d=1.0,double s=1.0):
 Duzina(d)
, Visina(v)
, Sirina(s)
{
}

CKutija::~CKutija()
{
}

void CKutija::PokaziVolumen() const
{
    cout<<"Volumen od Kutije je :"<<Volumen()<<endl;
}

double CKutija::Volumen()const
{
    return Duzina*Visina*Sirina;
}

Sad druga klasa.
KartonKutija.h:

 

#pragma once
#include "Kutija.h"
class CKartonKutija:public CKutija   //ovdje vidite naslijedjivanje
{
public:
    CKartonKutija(double,double,double);
    ~CKartonKutija();
    double Volumen(void)const;
protected:
    double Visina;
    double Duzina;
    double Sirina;
};

....sad KartonKutija.cpp:

#include "KartonKutija.h"

CKartonKutija::CKartonKutija(double v=1.0,double s=1.0,double d=1.0):
 CKutija(v,s,d)
{
}

CKartonKutija::~CKartonKutija()
{
}

double CKartonKutija::Volumen() const
{
    return 0.50*Duzina*Visina*Sirina;    //nasa posebna funkcija
}

...i sad glavni program:
glavni.cpp:

 

#include <iostream>
#include "KartonKutija.h"
using namespace std;
int main()
{
    CKutija m_Kutija(3.9,4.7,4.0);
    CKartonKutija m_KartonKutija(3.9,4.7,4.0);
    m_Kutija.PokaziVolumen();
    m_KartonKutija.PokaziVolumen();
    cout<<endl;
    return 0;
}

 

...evo koda i kad ga izvršite vidjet ćete da dolazi do korištenja funkcije iz Base class jer
nismo sad upotrijebili virtual ali u ispravci (ima još jedna greška u kodu koju ću slijedeći put objasniti ,a pokušajte je i vi naći)
hoćemo i sad već lakše razumijete zašto virtual...zato da program
zna koju funkciju hoćemo pozivajući je kao da pozivamo funkciju iz Base class a u biti se radi o Derived class funkciji.
Nastavljamo kad budem mogao.Imate dosta zasad.
Evo sad ću ovaj kod samo malo izmjeniti a vi svakako to proučite i obratite pažnju gdje i kako sam
primjenio ključnu riječ virtual:  

 

Kutija.h :

 

 

#pragma once

class CKutija
{
public:
    CKutija(double,double,double);
    ~CKutija(void);
    void PokaziVolumen(void)const;
    virtual double Volumen()const;  //takodjer i ovdje moramo dati do znanja
    //da postoje dvije funkcije i kljucna rijec nam je virtual
protected:
    double Duzina;
    double Visina;
    double Sirina;
};

 

Kutija.cpp

 

#include "Kutija.h"
#include <iostream>
using namespace std;
CKutija::CKutija(double v=1.0,double d=1.0,double s=1.0):
 Duzina(d)
, Visina(v)
, Sirina(s)
{
}

CKutija::~CKutija()
{
}

void CKutija::PokaziVolumen() const
{
    cout<<"Volumen od Kutije je :"<<Volumen()<<endl;
}

double CKutija::Volumen() virtual const
{
    return Duzina*Visina*Sirina;
}

 

 

KutijaKarton.h:

 

#pragma once
#include "Kutija.h"
class CKartonKutija:public CKutija //naslijedila je cijelu CKutija klasu
{//probjate staviti private ili protected umjesto public i pogledajte
    //sto ce se dogoditi?

public:
    CKartonKutija(double,double,double);
    ~CKartonKutija();
    virtual double Volumen()const;  //vlastita funkcija
    //ovo nam ne treba jer ova klasa naslijedjuje sve od Base class CKutija
//protected:
//    double Visina;
//    double Duzina;
//    double Sirina;
};
//#pragma once vam je umjesto #ifndef i #define i na kraju #endif
//mislim da sam to vec negdje na ovim stranicama objasnjavao pa ponovite

KutijaKarton.cpp:

 

#include "KartonKutija.h"

CKartonKutija::CKartonKutija(double v=1.0,double s=1.0,double d=1.0):
 CKutija(v,s,d)
{
}

CKartonKutija::~CKartonKutija()
{
}

  double CKartonKutija::Volumen()virtual const
{
    return 2*Duzina*Visina*Sirina;   //ovdje sam samo sve pomnozio s dva
}                                    //i eto vam vlastite funkcije za CKartonKutija klasu

 

glavni.cpp:

 

#include <iostream>
#include "KartonKutija.h"
using namespace std;
int main()
{
    CKutija m_Kutija(2.0,3.0,4.0);
    CKartonKutija m_KartonKutija(2.0,3.0,4.0);
    m_Kutija.PokaziVolumen();      //u programu pozivamo kao prvu funkciju
    m_KartonKutija.PokaziVolumen(); //ima isto ime eto nam poziva virtualne funk.
    cout<<endl;
    return 0;
}
//to je primjer polimofirzma u OOP-u

Vi s deklaracijom virtualne funkcije u Base klasi dajete do znanja prevodiocu da postoji neka druga funkcija
koju mora primjeniti a ne svoju originalnu,a ta druga se nalazi u izvedenoj(klasi koja naslijedjuje) klasi naravno
s ključnom riječi virtual.A način na koji ste pozvali i dali do znanja da se radi o virtualnoj funkciji je naravno
stavranje objekta (instance) koji vodi do naše Derived klase.
Takovo povezivanje (linkanje) funkcije pri prevodjenju s virtualnim funkcijama je tkz. dynamic linkage za razliku od
prvog primjera koda bez virtual mehanizma koji onda nosi naziv static linkage   .
Znači,da bi se sama funkcija ponašala kao virtalna moramo znači imati isto ime,parametre,i return tip i ako je const
mora biti i u Derived klasi const.....znaci sve mora biti isto!!!!    
Isto ime a različito ponašanje...kao jedan film u kojem netko ima ulogu dvostruke ličnosti-polimorfizam.

Dolje niže ću vam samo malo slika dati kako to izgleda u VS-u
a slično mora izgledati i u Dev-u.
U VS-u : file -new project(pod general) ->empty (i date ime)....zatim na ...header i desni klik i dodajete(add) header file(narvno jezik je c++ pri odabiru)
Na isti način vi dodajete i na source file ali ovaj put cpp file i nakraju naravno glavni.cpp.
Visual studio generira više od pola koda za vas a vi samo dodajete to treba.U Dev-u sve morate malo sami....ponovite
kako sam to radio na ovim stranicama (potražite) ...razdvajanje deklaracije i definicije.....jedno ide u cpp file a drugo u header file.

U ovom postu sam se eto dotakao pojma polimorfizam koji sam realizirao kroz virtalni mehanizam.
Napominjem "dotakao",samo vam približio te pojmove da ih malo bolje razumjeteu vašem daljnjem učenju!
U ovom postu još ću se dotaknuti ostvarivanja virtualnog mehanizma preko pokazivača i  i uporaba  referenci
sa virtualnim mehanizmom jer se radi o jednom te istom programu i zato je lakše za sve ,samo dodajemo kod!
A poseban post će biti o apstraktnoj klasi i čistoj virtulanoj funkciji...samo najava.

Sad samo naslov pa kad stignem.

...Pokazivači i Virtualne funkcije

 

Evo koda gdje su jasno pokazane izmjene koje sam načinio i proučite ih ,izmjene su samo u glavni.cpp

i mislim da ćete lako shvatiti o čemu se radi ,objašnjenje naravno slijedi :

 

#include <iostream>
#include "KartonKutija.h"
using namespace std;
int main()
{

    CKutija m_Kutija(2.0,3.0,4.0);
    CKartonKutija m_KartonKutija(2.0,3.0,4.0);
    //m_Kutija.PokaziVolumen();      //u programu pozivamo kao prvu funkciju
    //m_KartonKutija.PokaziVolumen(); //ima isto ime eto nam poziva virtualne funk.
    //cout<<endl;
    CKutija* pKutija =0;  //formiramo pokazivac tipa CKutija na objrkte klase CKutija
    pKutija =&m_Kutija;    //pokazivac na adresu objekta(instance) CKutija
    pKutija->PokaziVolumen(); //ovdje pozivamo funkciju base klase
    pKutija = &m_KartonKutija;//sad na drugi objekt od derived klase(dinamicko vezivanje)
    pKutija->PokaziVolumen(); //ovdje pozivamo funkciju derived klase
    cout<<endl;

    return 0;
}
//to je primjer polimofirzma u OOP-u
//sad preko pokazivaca smo napravili pozivanje funkcije
//takodjer primjetite da i preko pokazivaca mozemo realizirati virtualni mehanizam

_____________________________________________________________________________________________

@Tracer
Kolega nema tu ispravljanja vi samo dodajte što ja ne objasnim ili ne napišem jer smo tu svi zajedno da kompletiramo
koliko je to moguće ovaj tutorijal i stoga svaki post koji postate u svrhu boljeg objašnjenja ili ispravka je dobro došao!

__________________________________________________________________________________________

Virtualne funkcije se mogu dakle pozivati i oreko pokazivača i da ponovimo:
Polimorfizam je način na koji objekt izvršava operaciju koja pripada izvedenoj klasi iako se tom objektu
pristupa kao primjerku "base" klase.

Uporaba reference u virtualnom mehanizmu

 

Ako definiramo funkciju s referencama a Base klasu kao parametar u toj funkciji
tad možemo prenijeti kao argument te funkcije objekt Derived klase.Sve to nam omogućava pravilno pozivanje
virtualne funkcije.
Naravno ,da morate ponoviti prijenos po vrijednosti i referenci ranije na ovim tutovima.
Sad opet malo prepravimo kod u glavni.cpp :

 

#include <iostream>
#include "KartonKutija.h"
using namespace std;
void izlaz_novi(const CKutija &aKutija);//parametar funkcije je objekt(adresa)CKutija base klase
int main()
{

    CKutija m_Kutija(2.0,3.0,4.0);
    CKartonKutija m_KartonKutija(2.0,3.0,4.0);
    //m_Kutija.PokaziVolumen();      //u programu pozivamo kao prvu funkciju
    //m_KartonKutija.PokaziVolumen(); //ima isto ime eto nam poziva virtualne funk.
    //cout<<endl;
    //sad idemo na pokazivac u virtalnim funkcijama
    //__________________________________________________________________________________
    //CKutija* pKutija =0;  //formiramo pokazivac tipa CKutija na objrkte klase CKutija
    //pKutija =&m_Kutija;    //pokazivac na adresu objekta(instance) CKutija
    //pKutija->PokaziVolumen(); //ovdje pozivamo funkciju base klase
    //pKutija = &m_KartonKutija;//sad na drugi objekt od derived klase(dinamicko vezivanje)
    //pKutija->PokaziVolumen(); //ovdje pozivamo funkciju derived klase
    //______________________________________________________________________________
    //ovdje zapocinjemo program kojim upotreblavamo reference
    izlaz_novi(m_Kutija);
    izlaz_novi(m_KartonKutija);
    cout<<endl;

    return 0;
}
//to je primjer polimofirzma u OOP-u
//sad preko pokazivaca smo napravili pozivanje funkcije
//takodjer primjetite da i preko pokazivaca mozemo realizirati virtualni mehanizam
//sad ovdje funkcija i definicija
 void izlaz_novi(const CKutija &aKutija)
{
    aKutija.PokaziVolumen();   //pozivamo funkciju preko objekta
}

 

 

 

....i sad primjetite da funkcija izlaz_novi prenosi objekat kao argument iz Derived klase i naravno
izvršava se pravilna virtualna funkcija.

Sad ćemo prijeći na čiste virtualne funkcije i abstraktne klase i razlog zašto ih trebamo iako me kolega
Tracer malo pretekao ali što više primejra i objašnjenja doprinosi bogatstvu ovog tutorijala.
_________________________________________________________________________

PS:kad uhvatim vremena.

 

 

 

 

 

 

 

 

 

 

 

 

solution explorer u VS-u solution explorer u VS-u
sad već kad smo nešto i dodali sad već kad smo nešto i dodali
ovdje vidite i cpp file glavni. ovdje vidite i cpp file glavni.
ovdje je naš primjer koji ovako izleda kad je gotov ovdje je naš primjer koji ovako izleda kad je gotov
v_maxcpp
Poruka je uređivana zadnji put sub 9.8.2008 13:16 (v_maxcpp).
17 godina
protjeran
offline
C++ tutorijali...

Ključna riječ friend općenito označava potpunu slobodu pristupa, a to ne mora samo biti riječ o friend klasi, već i npr. globalnim funkcijama:

 

class Tocka
{
    int x, y;
    friend int GetX(Tocka A);
    friend int GetY(Tocka A);
};
int GetX(Tocka A){
    return A.x;
}
int GetY(Tocka A){
    return A.y;
}

 

Namigiva good work.

Poruka je uređivana zadnji put pet 8.8.2008 17:42 (Tracer).
Moj PC  
0 0 hvala 0
17 godina
protjeran
offline
RE: C++ tutorijali...

 

Kolega, ne želim ispasti babaroga koja je tu da bi vas ispravljala, nadopunjavala ili sl., no trebalo bi spomenuti i da su virtualne funkcije nužne u nekim situacijama čak i kad nemaju eksplicitnu svrhu u deriviranim klasama. Primjerice, kada se radi dynamic_cast pretvorba. Također, možda ste trebali staviti i primjer za abstraktnu klasu tj. čiste virtualne funkcije. Npr.:

 

class Zivotinja
{
    public:
        virtual void Vrsta(){}
};
class Pas : public Zivotinja
{
    public:
        void Vrsta(){
            cout << "Pas\n";
        }
};
class Macka : public Zivotinja
{
    public:
        void Vrsta(){
            cout << "Macka\n";
        }
};
int main()
{
    Pas Rex;
    Macka Mac;
    Zivotinja *Ziv;

    Ziv = &Rex;
    Ziv->Vrsta(); // Pas
    Ziv = &Mac;
    Ziv->Vrsta(); // Macka
    return 0;
}

Ovdje je riječ o još jednom primjeru upotrebe virtualnih funkcija gdje je funkcija Vrsta ona koja za svaku derivaciju treba imati različito tijelo. No abstraktna klasa bi bila ovakva:

 

class Zivotinja
{
    public:
        virtual void Vrsta() = 0;  // čista virtualna funkcija
};

Važnost abstraktne klase je u tome što ne postoji tijelo virtualne funkcije, pa zato ne može postojati niti jedna instanca takve klase. Npr.:

 

Zivotinja Jelen; // greška! klasa je abstraktna
Zivotinja* pJelen; // ok!

 

Znači, dopušta se adresiranje na derivacije abstraktne klase preko pokazivača, no ne i direktna postojanost instance bazne klase.

 

 

Poruka je uređivana zadnji put sub 9.8.2008 12:11 (Tracer).
17 godina
neaktivan
offline
RE: C++ tutorijali...
Kolega bravo jer svrha je što više objašnjenja to bolje....a slijedeći post će biti o čistoj virtualnoj funkciji i abstraktnim klasama.
v_maxcpp
17 godina
neaktivan
offline
RE: C++ tutorijali...

 

 

...ČISTA VIRTUALNA FUNKCIJA I ABSTRAKTNE KLASE(KLASA)

 

 

Ovako...nekad će nam zatrebati virtualna funkcija unutar Base klase koju ćemo
morati redefinirati (funkciju)u Derived klasi da odgovara objektu te klase.Sad da bi to ostvarili
moramo napraviti klasu koja će izvedenim klasama pružiti mogućnost da te
izvedene klase same definiraju sebi virtualnu funkciju a u Base klasi ćemo samo
izvršiti njenu deklaraciju i ništa više,sama klasa Base klas neće imati nikakve
varijable,samo čista deklaracija virtualne funkcije bez sadržaja i postaviti ćemo je
jednako nuli....to se zove čista virtualna funkcija  "pure virtual function".Derived
klase znači imaju sad mogućnost(moraju dati tijelo ako je žele koristiti) da
definiraju ili redefiniraju virtualnu funkciju kako njima "paše".U našem primjeru
imamo još jednu definiciju funkcije kao virtual i ona je dio Base klase ali koja se
može redefinirati jer je virtual.Vi naravno upamtite čistu virtual funkciju koja nam
koristi pri dinamičkom vezanju u toku prevođenja programskog koda....znači nema
statičke virtualne funkcije da se tako izrazim slikovito(nema ranog vezanja nego
kasnog iliti dinamičkog).

Znači ,klasa koja sadrži čistu virtualnu funkciju je abstraktna klasa.Zovemo je

abstraktna jer ne možemo stvarati objekte kao njezine instance(što je kolega

tracer lijepo prikazao u primjeru) i ona postoji samo zato da se definira u izvedenoj

klasi koja je dinamički koristi,mislim na čistu virtualnu funkciju.Ako sama izvedena

klasa opet u sebi sadrži čistu virtalnu klasu tad je i ta Derived klasa Abstraktna

klasa!
Sad ćemo na sam primjer i onda kad stigem sve ponovimo i naravno objasnim

malo i sam primjer :

....sami  kod sam rasporedio tako da su sve klase u header file-u a imamo samo
jedan glavni.cpp u kojem sve izvršavamo...kasnije u toku izlaganja i objašnjavanja koda
i u slikama vam to malo prikažem:

Abstraktna.h :

 

#pragma once
#include<iostream>
using namespace std;

class CAbstraktna
{
public:
    virtual double Volumen() const =0;  //virtualna funkcija cista!!
    virtual void PokaziVolumen()const
    {
        cout<<"Volumen je ove druge : "<<Volumen()<<endl;
    }
};

Kutija.h:

 

#pragma once
#include "Abstraktna.h"
#include<iostream>
using namespace std;

class CKutija:public CAbstraktna
{
public:
    virtual void PokaziVolumen() const
    {
        cout<<"Kutija ima volumen : "<<Volumen()<<endl;   //ovdje imamo vlastititu virtualnu PokaziVolumen funkciju
    }
virtual double Volumen() const   //virtulana funkcija
{
    return Duzina*Visina*Sirina;
}
//konsruktor
CKutija(double v= 1.0,double s = 1.0,double d=1.0):
Duzina(d),Visina(v),Sirina(s){}
protected:
    double Visina;
    double Duzina;
    double Sirina;
};

KutijaKutijica.h :

 

#pragma once
#include "Abstraktna.h"//takodjer koristimo abstraktnu klasu
#include <iostream>
extern const double PI;    //pi je definirano negdje drugdje a s extern ključnom riječju "ubacujemo "u header link za definiciju PI-a
using namespace std;

    //primjetite da nema PokaziVolumen funkcije i tad se koristi virtualna funk. iz base klase

class CKutijaKutijica:public CAbstraktna
{
public:
    virtual double Volumen()const
    {
        return 0.25*PI*Promjer*Promjer*Visina;
    }
    //konstruktor
    CKutijaKutijica(double v= 4.0,double p=2.0):
    Visina(v),Promjer(p){}
protected:
    double Promjer;
    double Visina;
};

 

glavni.cpp

 

#include <iostream>
#include "Kutija.h"
#include "KutijaKutijica.h"
using namespace std;
const double PI = 3.14159265;   //ovdje je definicija pi na globalnoj razini
int main()
{
    CAbstraktna* pokC1 = new CKutija(5.0,7.0,4.0);   //probajte stvoriti objekte CAbstarktne i vidjeti ćete grešku
    
    CAbstraktna* pokC2 = new CKutijaKutijica(5.5,3.0);
    pokC1->PokaziVolumen();
    pokC2->PokaziVolumen();
    delete pokC1;
    delete pokC2;

    
return 0;
}

 

Naravno,ponovite dinamičku alokaciju memorije s operatorima new i delete!

Znači mi smo u glavnom programu deklarirali dva pokazivača tipa naše Base klase
jer na taj način dopiremo do naše Base klase,jer ne možemo stvarati objekte kao
njezine instance jer je to Abstraktna klasa!


Sad možemo spremiti adresu u taj pokazivač,adresu objekta Derived klase!
Mi smo dodijelili "free store" pomoću new naredbe jer dinamički upravljamo
memorijom i na kraju je oslobađamo s delete naredbom(obvezatno).


Naravno ,objekti u izvedenim klasama se dinamički povezuju i stoga smo i mi upotrijebili
dinamičko upravljanje memorijom!
Pokazivač Base klase može sadržavati objekte(kojih može biti puno) svake izvedene klase iz naše Base
klase!

 

Sad ćemo sve ponoviti........
Klase koje nemaju instance(objekte),već nam služe samo da iz njih iizvedemo druge klase zovemo-Abstraktne klase.

U C++ jeziku svaka abstraktna klasa sadrži barem jednu čistu virtualnu funkciju.

To znači da je ta funkcija u Abstraktnoj klasi samo deklarirana a definiciju te čiste virtualne funkcije dati će izvedene klase!

Sama njena deklaracija u osnovnoj klasi završava s =0;(tkz.specifikator)

virtual double Volumen() const =0;

Klasa je apstraktna ako sadrži čistu virtualnu funkciju...znači ne mogu se stavrati objekti.
Ako mi u izvedenoj klasi iz te osnovne klase ne deklariramo virtalnu funkciju čistu tad i ta izvedena klasa postaje abstraktna!
Apstraktna klasa može imati podatke(varijable)..nevirtualne funkcijske članice i obične funkcije virtualne.

Recimo da bi to bilo to zasad.

 

 

solution explorer view...proučite solution explorer view...proučite
class view ...sad pogledajte cijelo stablo !!! class view ...sad pogledajte cijelo stablo !!!
v_maxcpp
Poruka je uređivana zadnji put sub 9.8.2008 22:09 (v_maxcpp).
17 godina
neaktivan
offline
RE: C++ tutorijali...

 



INDIREKTNA BASE KLAS

 

uvod:

 

Dosad smo u biti govorili o direktnim izvedenim klasama a sad ću se dotaknuti indirektnog
naslijeđivanja ali ćemo prvo samo malo ponoviti o direktnom naslijeđivanju.

To je samo uvod što će biti u ovom postu ,a također ću se dotaknuti i tkz.
Nested Classes-ugniježđenih klasa(nadam se da sam dobro napisao).
Ali mislim da će proći vremena prije nego završim  ovaj post,stoga budite strpljivi jer pišem kad mogu.
____________________________________________________________________________

 

Indirektna Base klasa


Da ne bi komplicirali samo ću na prijašnje programe koji imaju jednu Base klasu od koje
imamo direktne izvedene klase tj. Base klasa Abstraktna je direktna za njih a sad
onu koju budem dodao ona će biti izvedena iz klase CKutija što automatski znači
da je CKutija sad (koja je izvedena iz Abstraktne klase) postaje direktana Base klasa za našu
klasu koju ću izvesti uz nje.OPet po toj logici ta naša izvedena klasa iz Ckutija klase
indirektno izvedena iz CAbstarktne klase što znači da je Abstraktna klasa koja je Direktna za
naše dvije klase sad Indiorektna Base klasa za našu novu klasu koju ćete naravno
sad vidjeti  u kodu.
Znači samo ću dodati novi header file u kojem će biti naša nova klasa kojoj je Base
klasa CKutija a CKutja je izvedena iz CAbstarktne i na taj način CAbstrakna je Indirektna
Base Klasa toj našoj novoj klasi ,a direktna joj je CKutija!

Abstraktna.h

#pragma once
#include<iostream>
using namespace std;

class CAbstraktna
{
public:
    virtual double Volumen() const =0;  //virtualna funkcija cista!!
    virtual void PokaziVolumen()const
    {
        cout<<"Volumen je ove druge : "<<Volumen()<<endl;
    }
};

Kutija.h

#pragma once
#include "Abstraktna.h"
#include<iostream>
using namespace std;

class CKutija:public CAbstraktna
{
public:
    virtual void PokaziVolumen() const
    {
        cout<<"Kutija ima volumen : "<<Volumen()<<endl;
    }
virtual double Volumen() const   //virtulana funkcija
{
    return Duzina*Visina*Sirina;
}
//konsruktor
CKutija(double v= 1.0,double s = 1.0,double d=1.0):
Duzina(d),Visina(v),Sirina(s){}
protected:
    double Visina;
    double Duzina;
    double Sirina;
};

 

KutijaKutijica.h

 

#pragma once
#include "Abstraktna.h"//takodjer koristimo abstraktnu klasu
#include <iostream>
extern const double PI;    //pi je definirano negdje drugdje
using namespace std;

    

class CKutijaKutijica:public CAbstraktna
{
public:
    virtual double Volumen()const
    {
        return 0.25*PI*Promjer*Promjer*Visina;
    }
    //konstruktor
    CKutijaKutijica(double v= 4.0,double p=2.0):
    Visina(v),Promjer(p){}
protected:
    double Promjer;
    double Visina;
};

IndirektKutija.h

Sad dodajemo znači novi file i to je naša nova klasa koja za Base klasu ima CKutija :

#include <iostream>
#include "Kutija.h"     //znači tu nije "Abstraktna.h" ona je indirektna base class
class CIndirektKutija : public CKutija
{
public:
    //sad ovdje definiramo virtualnu funkciju za ovu klasu
    virtual double Volumen() const
    {
        return 0.50*Duzina*Visina*Sirina;
    }
    //konstruktor
    CIndirektKutija(double v,double s,double d):CKutija(v,s,d)
    {}
};

 

glavni.cpp

 

#include <iostream>
#include "Kutija.h"
#include "KutijaKutijica.h"
#include "IndirektKutija.h"   //ovdje uključujemo našu novu klasu!!!!
using namespace std;
const double PI = 3.14159265;   //ovdje je definicija pi na globalnoj razini
int main()
{
    CAbstraktna* pokc = new CKutija(3.0,4.0,5.0);
    CKutijaKutijica moja_Kutija(2.3,4.5);
    CIndirektKutija I_Kutija(4.5,2.3,4.0);
    pokc->PokaziVolumen();
    delete pokc;       //moramo osloboditi mjesto(u free store) za smjestaj adrese
     pokc=&moja_Kutija;
     pokc->PokaziVolumen();
     pokc = &I_Kutija;
     pokc->PokaziVolumen();
     cout<<endl;
return 0;
}

 

Naravno da slijedi  objašnjenje ali neka sad malo proučavajte!
Imate dole i slike solution explorera i class view(tu obratite pažnju na to tko je kome base klasa)
Na slici dolje sam i dodao grafički prikaz naslijeđivanja među ovim primjerima!!!!
____________________________________________________________________________________________
Mala digresija prije nego se vratimo na objašnjavanje navedenog primjera.

Višestruko naslijeđivanje tj.izvođenje klasa

Klasa se može znači izvesti iz više osnovnih klasa.Tad izvedena klasa posjeduje sve članove svojih osnovnih klasa ali one članove koji su deklarirani u njo samoj.
Tako izvedena klasa se izvodi navođenjem u zaglavljima deklaracije svake osnovne klase iz koje potiče!
Oblik je:
class Derived : public Osnovna1,public osnovna2,public Osnovna3
{
};

Sam poredak navođenja osnovnih klasa u deklaraciji izvedene klase nije nužno ni raspored podobjekata osnovnih klasa unutar objekta izvedene klase!
Jedna klasa ne može biti navedena nekoliko puta kao direktna klasa ,ali kao indirektna može.
Primjer:
class A
{};
class B :public A{};
clas C:public A{};
clas D:public A,public B{};


Vidite da je više puta navedena u D klasi jer je indirektana osnovna klasa.
Sve ovo se zove "multiple inheritance" to je naslov samo na engleskom originalu.
Eto i ovoga sam se dotaknuo.
O naslijeđivanju i ključnim riječima protected: , private: ,i  public:
mislim da sam prije rekao  ,stoga malo se vratite unazad i ponovite.
________________________________________________________________________________________

Sad se možemo vratiti...

Abstarktna klasa(base) u našem primjeru ima čistu virtualnu funkciju,Volumen().
U main programu pozivamo PokaziVolumen tri puta koristeći isti pokazivač
naše base klase(Apstraktne).Ali taj pokazivač sadrži adresu tri objekta iz tri različite klase svaki put kad je funkcija pozvana.
Bitno je reći da je funkcija pozvana za ovisno koji tip(instanca klase) je preko pokazivača pozvana!
Nadam se da ste shvatili sve ovo ,ako uporno vježbate red po red vjerujte da ćete napredovati!
_________________________________________________________________________________________

Slijedeći naslov je :


VIrtualni Destruktor

U ovom osvrtu na virtualne destruktore koristiti ćemo naravno program koji smo dosad koristili.

Sad ćemo u svaku klasu dodati po destruktor i kad pokrenete program pogledajte što se zbiva.
Pogledajte koji su destruktori pozvani i vidjet ćete da imamo problema s pozivanjem destruktora

koji su povezani s dinamičkom memorijom!

Abstraktna.h :

#pragma once
#include<iostream>
using namespace std;

class CAbstraktna
{
public:
    ~CAbstraktna()    //znaci sad dodajemo destruktor u svaku nasu klasu
    {
        cout<<"Pozivamo destruktor od Abstraktne klase!"<<endl;
    }
    virtual double Volumen() const =0;  //virtualna funkcija cista!!
    virtual void PokaziVolumen()const
    {
        cout<<"Volumen je ove druge : "<<Volumen()<<endl;
    }
};

 

Kutija.h :

 

#pragma once
#include "Abstraktna.h"
#include<iostream>
using namespace std;

class CKutija:public CAbstraktna
{
public:
~CKutija()
    {
        cout<<"Pozivamo destruktor od CKutija klase!"<<endl;  //evo ga i ovdje
    }
    virtual void PokaziVolumen() const
    {
        cout<<"Kutija ima volumen : "<<Volumen()<<endl;
    }
virtual double Volumen() const   //virtulana funkcija
{
    return Duzina*Visina*Sirina;
}
//konsruktor
CKutija(double v= 1.0,double s = 1.0,double d=1.0):
Duzina(d),Visina(v),Sirina(s){}
protected:
    double Visina;
    double Duzina;
    double Sirina;
};

 

KutijaKutijica.h :

#pragma once
#include "Abstraktna.h"//takodjer koristimo abstraktnu klasu
#include <iostream>
extern const double PI;    //pi je definirano negdje drugdje
using namespace std;

    

class CKutijaKutijica:public CAbstraktna
{
public:
~CKutijaKutijica()
    {
        cout<<"Pozivamo destruktor od CKutijaKutijica klase!"<<endl;
    }
    virtual double Volumen()const
    {
        return 0.25*PI*Promjer*Promjer*Visina;
    }
    //konstruktor
    CKutijaKutijica(double v= 4.0,double p=2.0):
    Visina(v),Promjer(p){}
protected:
    double Promjer;
    double Visina;
};

 

 

IndirektKutija.h :

 

#include <iostream>
#include "Kutija.h"
class CIndirektKutija : public CKutija
{
public:
~CIndirektKutija()
    {
        cout<<"Pozivamo destruktor od CIndirektKutija klase!"<<endl;
    }
    //sad ovdje definiramo virtualnu funkciju za ovu klasu
    virtual double Volumen() const
    {
        return 0.50*Duzina*Visina*Sirina;
    }
    //konstruktor
    CIndirektKutija(double v,double s,double d):CKutija(v,s,d)
    {}
};

 

glavni.cpp:

 

...primjetite kakvu smo izmjenu(dodatak napravili)

#include <iostream>
#include "Kutija.h"
#include "KutijaKutijica.h"
#include "IndirektKutija.h"
using namespace std;
const double PI = 3.14159265;   //ovdje je definicija pi na globalnoj razini
int main()
{
    CAbstraktna* pokc = new CKutija(3.0,4.0,5.0);
    CKutijaKutijica moja_Kutija(2.3,4.5);
    CIndirektKutija I_Kutija(4.5,2.3,4.0);
    pokc->PokaziVolumen();
    cout<<"Sad brisemo CKutija!"<<endl;//ovo smo takodjer dodali
    delete pokc;    //moramo osloboditi mjesto(u free store) za smjestaj adrese
    //_______________________________________
    //ovaj dio smo dodali znaci opet dinamicko upravljanje memorije
    pokc = new CIndirektKutija(4.0,6.0,8.0);
    pokc->PokaziVolumen();
    cout<<"Sad brisemo CIndirektKutija!"<<endl;
    delete pokc;
    //________________________________________
     pokc=&moja_Kutija;
     pokc->PokaziVolumen();
     pokc = &I_Kutija;
     pokc->PokaziVolumen();
     cout<<endl;
return 0;
}

 

 

Znači sad smo u svaku klasu postavili i definirali destruktore!!!!!
Program izvršite i proučite!Vidjeti ćete da se ne pozivaju destruktori kako bi trebali!

Pogledajte koji su destruktori pozvani i vidjet ćete da imamo problema s pozivanjem destruktora
koji su povezani s dinamičkom memorijom!
Riješenje su Virtualni destruktori i sad kad pkenete progarm sve će biti ok.
Znači sad ispred svakog destruktora dodajte ključnu riječ virtual i riješen je problem  pozivanja destruktora!

virtual ~CIndirektKutija()
    {
        cout<<"Pozivamo destruktor od CIndirektKutija klase!"<<endl;
    }

....i tako ispred svakog destruktora da sad ja ne ponavljam kod i ispise.Pokrenite ga i uočite razliku!
Sad idemo malo pisati o ovim događanjima ,kolega tracer je već to lijepo ukratko objasnio.

Malo općenito:
Prvi destruktori koji se pozivaju su oni koji se određuju na temelju tipa objekta
a ne tipa pokazivača ili reference na objekt.
Destruktori osnovnih(Base) klasa uvijek su implicitno (automatski) pozivaju!
Destruktor može biti virtualni ali ne i konstruktor.
Pravilo je ako neka klasa ima virtualnu funkciju poželjno je da ima i virtualni destruktor!
Sad usporedba s virtualnim funkcijama:
Poziv same virtualne funkcije kad se poziva poziva se prema tipu objekta na koji pokazivač pokazuje a ne prema tipu pokazivača.
Poziv nevirtualne funkcije vrši se prema tipu pokazivača što znači da ćemo pozvati funkciju odakle pokazivač potječe.
Ako sama izvedena klasa ne definira svoju virtualnu funkciju tad se poziva funkcija iz osnovne klase ,to isto pravilo vrijedi i za destruktor
(sad vidite zašto moramo imati virtualni destruktor-da bi oslobodili točan dio memorije).
Ako se unutar konstruktora ili destruktora pozove virtualna funkcija pozvati će se ona koja odgovara klasi čiji je konstruktor ili destruktor.

 

Sad se vraćamo na objašnjenje našeg programa na temelju ovoga što ste pročitali.

Nakon brisanja Ckutije objekta  dolazi do poziva destruktora ali nam se prikazuje samo poziv destrektora CAbstraktne klase!
Sad smo dinamički stvorili prostor za CIndirektKutiju i nakon brisanja opte se pojavljuje destruktor samo CAbstraktne klase.
Za ostale objekte u kojima ne koristimo free store poziva se pravilinim redom
destruktori(malo ih razvrstajte i primetiti ćete kojim redom).
Znači ,mi imamo probleme samo s dinamičkim dijelom našeg programa gdje imamo problem s destruktorom kad se program izvodi (dinamički).
U oba slučaja se pogrešni destruktor poziva.On se poziva jer se poziv vrši statički pri prevođenju a ne izvršavanju(dinamički).
Kad se poziv vrši dinamički preko pokazivača tu nastaju problemi,jer kad mi s delete naredbom zbrišemo objekt
,programu ostaje samo tip pokazivača a to je tip osnovne klase i zato se poziva destruktor osnovne klase u oba slučaja!
Jer ako nema objekta na koji pokazuje program to riješava pozivajuću destruktor osnovne klase!
Znači mi moramo ovo riješiti dinamički u toku izvršavanja programa ,
a ne prevođenja (statički) i tako logički dolazimo do zaključka da nam trebaju virtualni destruktori!
Samo dodajte virtual  ispred definicije destruktora i to je to!Sad pogledajte redom kako se sve pravilno uništava!
Zašto konstruktor nije virtualan-zato jer se konstruktor poziva prije nego sam objekt zaživi i  zato nema smisla biti virtualan.

 

Još malo:


class Osnovna
{
   public:
     virtual ~Osnovna() ;//virtualni destruktor
     };
class Izvedena : public Osnovna
{  
    virtual ~Izvedena();  //virtualni destruktor ove klase
};
void oslobodi(Osnovna *poko)
{
    delete poko;
}
int main()
{
    Osnovna *poko = new Osnovna;
    Izvedena *poki = new Izvedena;
    oslobodi(poko);//   poziva se ~Osnovna
    oslobodi(poki)   // poziva se Izvedena;
    return 0;
}

U ovom oglednom primjeru vidite da se sve pravilno poziva iako je formalni argument pokazivač Osnovna(class) tipa .
Ali zato što je destruktor Osnovne klase virtualan sve se riješi pravilno i dinamički ,a da nije riješilo bi se statički(prema tipu pkazivača)!!!!  
Pozvao bi se destruktor Osnovna a ne Izvedana!
Nadam da sam dovoljno napisao o ovoj temi ,ako nisam uvijek me se može nadopuniti ili ispraviti!
Dolje vam je slika izvršenog programa s virtualnim destruktorima i pogledajte red kako se izvršavaju
onako kako treba.

Zasad toliko!
Slijedeći post(posebno) će biti o ugniježđenim klasama.
Nested Classes.
____________________________________________________________

 

 

 

 

solution explorer-primjetite dodanu klasu(header) solution explorer-primjetite dodanu klasu(header)
class view-primjetite i proučite base i derived(tko je kome) class view-primjetite i proučite base i derived(tko je kome)
HIJERARHIJA I pokazatelj direktnog i indirektnog načina HIJERARHIJA I pokazatelj direktnog i indirektnog načina
cmd virtualni destruktori. cmd virtualni destruktori.
v_maxcpp
Poruka je uređivana zadnji put pon 11.8.2008 18:40 (v_maxcpp).
17 godina
protjeran
offline
RE: C++ tutorijali...

Samo bih nadodao još nešto glede virtualnih funkcija... Naime, destruktor klase također može biti virtualan, dok to konstruktor ne može biti. Razlog je tome što virtualna tablica nije dostupna u vrijeme kreiranja objekta, ali zato prilikom njegova uništenja virtualni destuktor može itekako koristiti. Npr.:

 

class Bazna
{
    public:
    virtual ~Bazna(){
        cout << "Destruktor bazne klase...\n";
    }
};
class Derivacija : public Bazna
{
    public:
    ~Derivacija(){
        cout << "Destruktor derivacije...\n";
    }
};

 

Kada se uništava objekt derivacije u pravilu se prvo poziva destruktor derivacije klase a zatim destruktor bazne klase. No, ako imamo ovu situaciju:

 

Bazna* X = new Derivacija;
delete X;

 

U ovom slučaju po definiciji (deklaraciji) X je pokazivač koji pokazuje na objekt bazne klase, no zapravo pokazuje na objekt derivacije. Međutim, zbog deklaracije prilikom oslobađanja memorije poziva se samo destruktor bazne klase. No, ako je destruktor bazne klase virtualan prevoditelj će shvatiti da je X zapravo derivacija i prvo će pokrenuti destruktor derivirane klase, a tek onda destruktor bazne klase. Ovo često zna spasiti od mnogih memory leakova...

 

 

Poruka je uređivana zadnji put ned 10.8.2008 0:44 (Tracer).
17 godina
neaktivan
offline
RE: C++ tutorijali...

Kolega se dotako pojma virtualne tablice ...pa malo ćemo o njoj da vam to bude
bar bližeu učenju i razumijevanju a naravno razraditi ćemo i destruktore u drugim
postovima.
Kolega odlično piše!

         Realizacija virtualnog mehanizma kroz tkz. tablicu virtualnih funkcija.

             -za svaku klasu koja posjeduje virtualnu funkciju formira se tablica
             pokazivačana verzije virtualnih funkcija za tu klasu,
             svaki objekt klase koja sadrži virtualne funkcije
             naravno posjeduje pokazivač na tabelu virtalnih funkcija svoje klase.
             Taj pokazivač postavljaju  implicitno(bezuvjetno) konstruktori svake klase!

           -pri pozivanju virtualne funkcije,do funkcije se pristupa posredno preko
            pokazivača(kao što smo i vidjeli) na tabelu virtualnih funkcija unutar objekta i
           pokazivača iz tabele virtualnih  funkcija i to je dinamičko vezivanje.

      Da ponovimo,znači za svaku klasu kad je u pitanju samo jedno izvođenje ,virtualne funkcije se realiziraju
      tako da se za svaku klasu kreira kod za virtualnu funkciju(ali i za nevirtualne funk).
      Sad,na temelju toga se za svaku klasu kreira i tabela koja sadrži pokazivače na verzije virtualnih funkcija koja odgovara toj klasi.
      I to je ta virtualna tablica!!!!

      Svaki objekt klase sadrževati će jedan pokazivač koji ukazuje na tablicu   virtualnih funkcija
      klase kojoj taj objekat pripada.
      Sad samo ogledni primejer koji služi samo za učenje ali ne i kompajliranje:

      class Base
      {
           public:
              int x;
               virtual void a();
               virtual void b();
              
      };
      class Derived:public Base
      {
             int y;
               public:
               void b();
      };

U ovom gore primjeru tablica virtualnih funkcija će izgledati tako da za Base klasu sadrži
pokazivače na verzije funkcija  Base::a()    i   Base b();

Tablica za Derived klasu sadržavati će pokazivače na Base::a();    i na Derived b();
Zašto Derived b();?
Zato jer klasa Derived nije redefinirala virtualnu funkciju a()!!!
Zato zadržava verziju iz Base klase!


Svaki objekt  klase Base ima pokazivač na tablicu virtualnih funkcija klase B.
Svaki objekt klase Derived ima pokazivač na svoju tablicu virtualnih funkcija ,zanči
pokazivač na
Base::a() i na Derived b() funkciju.
Sad opet mala digresija.

Kada se poziva nevirtualna funkcija tad prevodilac generira kod za taj neposredan
poziv funkcije iz odgovarajuće klase.
Sad,to isto važi i za virtualnu funkciju kad se zna stvarni tip objekta!
Recimo iz našeg primejera :

y.b();         //sve znamo objekat je tipa Derived i zove b funkciju
to je statičko vezivanje!!!!

Sad,kad se poziva virtualna funkcija i kad ne znamo stvarni tip objekta,tj. u
programu mi vršimo poziv preko pokazivača ili reference ,tad se vrši dinamičko vezivanje!!!!

Tad kompajler gnerira kod za indirektan poziv funkcije(a ne direktan preko
objekta) preko
pokazivača na tablicu virtualnih funkcija!
Taj poziv(kod koji se stvara) treba prvo pročitati  pokazivač koji pokazuje na tablicu
(jer tip ne znamo) i zatim se pozove odgovarajuća virtualna funkcija na koju pokazivač pokazuje!!
Iz našeg primejra:

Derived y;
Base *poka = &y;
poka->b();


Iz ovog se vidi da je osigurano dinamičko vezivanje za objekt Derived klase.
Naravno ,malo se gubi na brzini jer za razliku od statičkog (direktnog) mi imamo
indirektno(preko pokazivača) dinamičko pozivanje,ali to je neznatni gubitak
same funkcionalnosti programa.
To je bilo ono osnovno što se tiče tablice virtualnih funkcija.
Tablica za klasu Derived izbleda ovako  tablicu dolje na slici vidite:

   Slika(DOLJE KLIKNITE)




Ovdje dolje vidite tablicu virtualnih funkcija za Klasu Derived!
(*(poka->virt_pokaziv[1])) (poka);    //generirani kod za poziv funkcije(semantika)
ovo [1] je drugi ulaz(prvi je naravno [0]) koji ukazuje na funkciju b().
Ovo je skraćeno što u tekstu sam napisao.Znači samo putokaz u vašem učenju!
Dalje o konstruktorima i destruktorima za virtualne klase ,i o tome ćemo
kad budemo.


TABLICA VIRTUALNIH FUNKCIJA ZA DERIVED KLASU TABLICA VIRTUALNIH FUNKCIJA ZA DERIVED KLASU
v_maxcpp
Poruka je uređivana zadnji put ned 10.8.2008 11:11 (v_maxcpp).
17 godina
neaktivan
offline
RE: C++ tutorijali...




NESTED CLASSES


Eto naslova pa krenimo.
Ništa pretjerano neću oko ove teme i naslova jer se taj pojam prožima i kroz
pojam petlji ,if-else uvjeta i namespace pojma,također i lokalno i globalno pojma.
Sve sam to dosad nekoliko puta spomenuo u ovim tutorijalima a za razumijevanje
ovog naslova to je potrebno i ponoviti!

 

Klasa može biti deklarirana unutar deklaracije druge klase i to je ugniježđena klasa.
Ime klase koja damo toj klasi lokalno je za klasu koja je okružuje.Imenu te klase
izvan okružujuće klase može se pristupiti operatorom razriješenja :: duplom dvotočkom.

Primjer je samo za razumijevanje ,kasnije ide program :

class Vanjsaka
{
   public:
     class Unutrašnja
     {
         //evo ovdje sve od unutrašnje
     };   //zatvaramo unutrašnju
  };  //zatvaramo vanjsku

int main() 
   {
       Vanjska a ;             //objekt vanjske
      Unutrašnja b;           //objekt unutrašnje ali tako ne možemo jer nije dostupna
                             //pokrivena je vanjskom
      Vanjska::Unutrašnja b ;  //ovako može ,sad imamo pristup preko operatora razriješenja.

}


Sama dubina dokle možemo ići s Nested klasom ovisi o programu i programeru,
C1::C2::C3........C::N....

int x,y  ;                      //deklaracija na globalnoj razini.
class Vanjska
  {
      public:
        int x ;                //lokalna za vanjsku klasu
          class Unutrašnja
            {
                 void funk(int a, Vanjsaka *pok)  //funkcija
                        {
                                  x= a;   //ovako ne može jer pristup x-u nije korektan!
                                 ::x=a;   //ovako može-pristup globalnom x
                                  y=a  //i ovako može pristup globalnom jer nema zabune!!!
                                  pok->x=a;  //i ovako može jer koristimo pokazivač!!!!!
                         }
            };
    };

Mislim da sam negdje pri početku govorio o oblastima važenja na globalnoj i
lokalnoj razini i o namespace pojmu,također i o petljama u petlji...ako ste
to dobro naučili tad vam i ugniježđene klase neće biti problem za razumijevanje.
Molim to ponoviti.
"Nested" class se može deklarirati u public ili private dijelu vanjske klase.
Vanjska klasa ima pristup public dijelu dok private dijelu  nema.
Same pristupe ćemo kad budemo napisali program da bi još bolje razumjeli ovo što je napisano  ,na kojem sve
što sam spomenuo ili bar dio ,će biti.
Opet da bismo olakšali učenje samo ćemo prijašnje programe malo "preraditi"
i dodati jednu ugniježđenu klasu.
To je ono što vas čeka kad uhvatim opet vremena.A sad ću samo dodati slike tog izmjenjenog programa
i cmd .exe kad ga izvršim.Primjetite da sam dodao još jednu klasu a u toj klasi je još jedna klasa(struktura).
To je samo uvid da sam završio ali želim to detaljno objasniti ali malo se odmaram.
Naravno da bi sve ovo razumjeli morate sve o klasama dosad proći i naravno ovaj program koji nas prati cijelo vrijeme!
To je ono što se iz slike vidi..
Sad program:


Abstraktna.h :
ona nam treba.

#pragma once
#include<iostream>
using namespace std;

class CAbstraktna
{
public:
    ~CAbstraktna()
    {
        cout<<"Pozivamo destruktor od Abstraktne klase!"<<endl;
    }
    virtual double Volumen() const =0;  //virtualna funkcija cista!!
    virtual void PokaziVolumen()const
    {
        cout<<"Volumen je ove druge : "<<Volumen()<<endl;
    }
};

 

Kutija.h (također nam treba):

 

class CKutija:public CAbstraktna
{
public:
~CKutija()
    {
        cout<<"Pozivamo destruktor od CKutija klase!"<<endl;
    }
    virtual void PokaziVolumen() const
    {
        cout<<"Kutija ima volumen : "<<Volumen()<<endl;
    }
virtual double Volumen() const   //virtulana funkcija
{
    return Duzina*Visina*Sirina;
}
//konsruktor
CKutija(double v= 1.0,double s = 1.0,double d=1.0):
Duzina(d),Visina(v),Sirina(s){}
protected:
    double Visina;
    double Duzina;
    double Sirina;
};

 

KutijaKutijca.h nam ne treba ali je u projektu.

#include <iostream>
extern const double PI;    //pi je definirano negdje drugdje
using namespace std;

    

class CKutijaKutijica:public CAbstraktna
{
public:
~CKutijaKutijica()
    {
        cout<<"Pozivamo destruktor od CKutijaKutijica klase!"<<endl;
    }
    virtual double Volumen()const
    {
        return 0.25*PI*Promjer*Promjer*Visina;
    }
    //konstruktor
    CKutijaKutijica(double v= 4.0,double p=2.0):
    Visina(v),Promjer(p){}
protected:
    double Promjer;
    double Visina;
};

 

IndirektKutija.h :

Ona nam treba.

#include <iostream>
#include "Kutija.h"
class CIndirektKutija : public CKutija
{
public:
~CIndirektKutija()
    {
        cout<<"Pozivamo destruktor od CIndirektKutija klase!"<<endl;
    }
    //sad ovdje definiramo virtualnu funkciju za ovu klasu
    virtual double Volumen() const
    {
        return 0.50*Duzina*Visina*Sirina;
    }
    //konstruktor
    CIndirektKutija(double v,double s,double d):CKutija(v,s,d)
    {}
};

 

Naša nova klasa koja sadrži "nested" strukturu .
neste.h

 

#pragma once
class CNested
{
private:
    struct CSpremiste
    {
        CKutija* pokKutija;       //pokazivaci na objekte
        CSpremiste* pokSlijedeci;    //pokazivaci na spremljene objekte ili na NULL
        //konstruktor
        CSpremiste(CKutija* pokK,CSpremiste* pokS):
        pokKutija(pokK),pokSlijedeci(pokS)
        {}
    };
    CSpremiste* pokVrh;
public:
    //sprema objekt u spremiste
    void Spremi(CKutija* pokKutija)//samo preko pokazivaca mozemo pristupiti
    {
        pokVrh = new CSpremiste(pokKutija,pokVrh);  //dinamicki na "heap"(free store)
    }
    CKutija* P()
    {
        if(pokVrh ==0)   //ako je spremiste prazno tad vrati NULL
            return 0;
        CKutija* pokKutija = pokVrh->pokKutija;  //dohvati kutiju iz spremista
        CSpremiste* pokCuvaj = pokVrh;     //spremi adresu na vrh "heap"
        pokVrh = pokVrh->pokSlijedeci;     //zatim na slijedeci
        delete pokCuvaj ;                  //stari zbrisi s "heap"
        return pokKutija;                  //opet na pocetak do kraja for petlje u glavnom.cpp
    }
};

///*vidite kako upravljamo memorijom*/

 

glavni.cpp:
I naravno glavni.cpp u kojem sam ostavio ono što ne koristimo da proučavate.

#include <iostream>
#include "Kutija.h"   //uklucujemo znaci klasu CKutija i njenu Base klasu
//#include "KutijaKutijica.h"
#include "IndirektKutija.h"    //ukljucujemo CIndirektKutija(a preko nje i CKutija i Base klasa)
#include "neste.h"
using namespace std;
//const double PI = 3.14159265;   //ovdje je definicija pi na globalnoj razini
int main()
{
    //CAbstraktna* pokc = new CKutija(3.0,4.0,5.0);
    //CKutijaKutijica moja_Kutija(2.3,4.5);
    //CIndirektKutija I_Kutija(4.5,2.3,4.0);
    //pokc->PokaziVolumen();
    //cout<<"Sad brisemo CKutija!"<<endl;//ovo smo takodjer dodali
    //delete pokc;    //moramo osloboditi mjesto(u free store) za smjestaj adrese
    ////_______________________________________
    ////ovaj dio smo dodali znaci opet dinamicko upravljanje memorije
    //pokc = new CIndirektKutija(4.0,6.0,8.0);
    //pokc->PokaziVolumen();
    //cout<<"Sad brisemo CIndirektKutija!"<<endl;
    //delete pokc;
    ////________________________________________
 //    pokc=&moja_Kutija;
    // pokc->PokaziVolumen();
 //    pokc = &I_Kutija;
    // pokc->PokaziVolumen();
    CKutija* pKutije[]=
    {
                          new CKutija(2.0,3.0,4.0),
                          new CIndirektKutija(2.0,3.0,4.0),
                          new CKutija(5.0,6.0,7.0),
                          new CIndirektKutija(5.0,6.0,7.0)
    };
    cout<<"Ovo polje kutija ima slijedece volumene : "<<endl<<endl;
    for (int x = 0; x<4; x++)
        pKutije[x]->PokaziVolumen();   //izracunava nase volumene
    cout<<endl<<endl;

    cout<<"Sad na spremiste : ";
    CNested* pokSpremi = new CNested;     //kreira spremiste
         for (int x = 0; x<4; x++)
             pokSpremi->Spremi(pKutije[x]);
        
         cout<<endl<<endl;
         cout<<"Obrnuti redoslijed : "<<endl<<endl;
       for (int x = 0; x<4; x++)
           pokSpremi->P()->PokaziVolumen();  //dohvaca objekte(adrese) i racuna volumen.


     cout<<endl;
return 0;
}

Mi smo znači stvorili novu klasu...CNested.
Koja je vanjska a unutrašnja je u biti struktura ali smo mogli staviti i class umjesto
strukture ,a struktura je stavljena jer je po defaultu public ,lakše je raditi sa
strukturom našoj vanjskoj klasi.
A u biti nam treba samo da spremamo podatke u našu ugniježđenu klasu(strukturu) ,i zato
nam odgovara struktura.U glavnom programu smo prvo kreirali polje pokazivača tipa (korisničkog-izvedenog).
Sad u njh možemo spremati adrese na kojima se nalaze naši objekti.
CKutija i CIndirektKutija po dva od svakog istih dimenzija.
Sve je dinamički kreirano jer mi želimo upravljati memorijom i biti sigurni da je sve
čisto nakon završetka programa.
Zatim ,izračunavamo volumen svake kutije preko funkcije PokaziVolumen() ,
jer smo preko pokazivača pozvali odgovarajuču funkciju za sve naše objekte.
Nakon toga mi opet (dinamički na "heap memoriji") stvaramo spremište za naše
objekte(adrese).I koristimo funkciju spremi()  samo za spremanje na novu lokaciju.
Naravno prvi u našem spremištu je zadnji koji je ušao!
Ponovite ono što sam rekao o spremanju na stog i uzimanju sa stoga!
Sad pomoću naše slijedeće funkcije dohvaćamo sve te adrese i objekte koji su na
tim adresama pomoću funkcije P()(opet dinamički upravljamo memoriojom) i
 odmah izračunavamo volumen opet!Ali sad zbog onog pravila spremanja na stog
....pokazuju se obrnutim redoslijedom.
Eto vidite kako sve klase međusobno surađuju u projektu i kako CNested pomoću
svojih funkcija prilazi ugniježđenoj strukturi ,a i razlog samog slobodnog
pristupa vanjske klase je zbog public strukture.
Sama struktura  je zaštićena od svih drugih korisničkih tipova ali mi pomoću
CNested klase i njezinih funkcijskih članica možemo manipulirati s vanjskim
podacima da bi ih kombinirali s ugniježđenim klasama koje su skrivene od "vanjskog svijeta".
Malo bolje sve proučite i vidjeti ćete kako sve lijepo surađuje u našem projektu.
Nemam vam što savjetovati nego da vježbate i sami počnete logički sve ovo povezati.
Na vama i vašem trudu je sve prepušteno.Do slijedećeg susreta.
____________________________________________________________________________

PS:
Ovdje imate link na YouToube video c++ tutorijale pa pogledajte:

 

Uživajte.
Slijedeći postovi će biti vezani uz C++/CLI tutorijale .NET
Zato ,downloadajte VS Express edition (2008 ili 2005)....i naravno SDK.
Imate upute koje vas vode.
________________________________________________________________________________

 

class view-nova klasa! class view-nova klasa!
class view-u toj klasi opet klasa(struktura) class view-u toj klasi opet klasa(struktura)
kako to izgleda u solution exploreru gdje sam dodao novi neste.h file u project! kako to izgleda u solution exploreru gdje sam dodao novi neste.h file u project!
...kad se kod izvrši!!! ...kad se kod izvrši!!!
...ovdje samo pogled kako smo uključili file a koji smo isključili iz projekta! ...ovdje samo pogled kako smo uključili file a koji smo isključili iz projekta!
v_maxcpp
Poruka je uređivana zadnji put sri 13.8.2008 19:42 (v_maxcpp).
17 godina
neaktivan
offline
RE: C++ tutorijali...

C++/CLI (Visual C++ u .NET Framework implementaciji)
 

ISO/ANSI obuhvaća i C++/CLI  kao proširenje tog standarda.
C++/CLI ima svoj vlastiti izlaz(pisanje) za ispis na ekranu(naredbe).
C++/CLI programiranje ima neka proširenja koja ću tokom tutorijala polako objašnjavati ,
tako da ćemo ići ukorak s programima koje budemo pisali i onda objašnjenja ,a ne sve odjedanput.
Raditi ćemo u Visual Studiu 2005 Professional edition.
Vi možete skinuti Express edition 2008 ili 2005.
C++/CLI radi na Microsoft Common Language Runtime što je
implementacija Common Language Infrastructure(CLI) standard.
.NET("dot net") Framework objedinjuje CLR  plus  .NET biblioteke i tako podupire aplikacije koje su pisane u CLR-u.
Nativni C++ je pisan s ISO/ANSI standardom ali može bez .NET platforme.
C++/CLI izvršva se pod okriljem CLR -a.(ISO/ANSI također)
.Ja neću govoriti koje jezike obuhvaća .NET Framework i  CLR jer mi ovdje govorimo o C++ kao sastavnom dijelu .NET-a.
Samo ću napomenuti da se sve prevodi u  tkz. MSIL (Microsoft Intermediate Language) .
Znači vi pišete u C++/CLI-u a MSIL ga prevodi u ono što razumije CLR.
Eto ,kratki osvrt,a tako je s bilo kojim jezikom baziranim na .NET platformi i CLR-u.Postoji dakle posrednik.
Još malo o CLR-u.To je standardna okolina za izvršavanje programa pisanih na više jezika  a jedan od njih je i C++.Radi se o ECMA standardu i na ovom
linku ako ste zainteresirani pogledajte:

http://www.ecma-international.org

ISO/ANSI standarde za c++ pogledajte na :

http://www.iso.org

Evo i link koji bolje objašnjava neke aspekte CLI/CLR

https://www.youtube.com/watch?v=NC5s__B6WVQ

Vi pokušajte samo poslušati o .NET Framewrku i CLR-u.

Vi možete koristiti sve ugrađene tipove koji su i u nativnom c++-u.
Imate i dva koja su specifična za C++/CLI.

long long veličine 8 bita za pozitivne i negativne raspone.
i  :
unsigned long long  veličine 8  bita ali samo za pozitivne raspone.

Razlika između nativnih i "managed" tipova je ta da tipovi koji su ugrađeni u C++/CLI mogu biti i ponašati se samo kao podaci ali i kao objekti ,
dakle     pripadnici su klasa!!!
Dio su System namespace.
Tako da ih u programu možete jednostavno deklarirati :
int broj = 10;
ili
System::Int32 broj = 10;
To znači da je tip int pripadnik namespace System .

int veličine 4 bita pripada CLI Klasi System::Int32.
Oba načina su ispravna ali samo sam vam pokazao kako kompajler tumači int kao
dio klase tj.kao objekt u CLI programiranju.
Kasnije vam mogu čitavu tabelu tih osnovnih vrijednosti kao dio klase System:: napisati ,
iako ćemo se tokom tuta susretati s time pa ću tamo usput to objašnjavati.
Malo sam sve ovdje pojednostavio, ali ne želim odmah na početku zakomplicirati.
Zasad je to sve malo imaginarno ali tokom tutorijalabiti će sve jasnije.
Stoga možemo odmah na prvi C++/CLI program koji dolazi kad budem imao vremena ,
sad ću  postati slike i mali uvid što ću objašnjavati u ovom početku (slike su dolje):

 

#include "stdafx.h"

using namespace System;

int main(array<System::String ^> ^args)//o ovome cemo kasnije tokom  tuta
{
    /*int a;
    int b;
    int c;*/
    System::Int32 a;   //ovo je pokazatelj da se radi o objektima
    System::Int32 b;    //stavite ovo pod komentare a unkomentirajte gornji dio
    System::Int32 c;    //opet isto ,ali samo sam htio pokazati OOP unutar tipova u C++/CLI
    a=9;
    b=5;
    c=a+b;
    Console::WriteLine(L"\n Ovo je ispis na ekranu pomocu ove naredbe : ");
    Console::WriteLine("\nConsole::Writeline()\n");
    Console::Write(L"a sad ispis rezultata(zbroja) : ");//skok u novi red
    Console::Write(c);//ostaje u istom redu!
    Console::WriteLine();//skok u novi red

    return 0;
}
//Ovdje samo pokazujem da neke mogucnosti C++/CLI programiranja obuhvacaju
//int tip kao objekt(instancu klase) sto cemo takodjer objasniti tokom tuta

WriteLine()  -funkcija je C++/CLI funkcija koja je definirana u Console klasi unutar
System namespaca.

Zasad upamtite da Console class predstavlja standardni input/output stream koji
komunicira s tipkovnicom i CMD-om .Sama funkcija doslovno znači ispiši i prijeđi u novi red.
Ispiši sve što se nalazi u mojim zagradama.Veliko slovo L znači da se radi o "Wide Charter String" slovima gdje svaki zank
zauzima dva bita.
Samo Write() funkcija je isto kao i prethodna ali sve je u jednom redu ispisano ,nema preskoka u new line iliti novi red.
Naravno tu je i operator razriješenja :: i naravno ponovite kako rade same funkcije iz tutova prije.
Inače ne počinjite ovaj tutorijal a da niste prošli onaj prethodni !
Znači ,sve što stavljamo inutar zagrada funkcija su naši argumenti.Mogu biti i prazne ,prihvaćaju znači nulu.
Ako ima više argumenata tad se odvajaju zarezima.
I sad ćemo se malo poigrati s tim funkcijama ispisa da vam uđu u malu naviku.

Pogledajte ispis ovog programa:

#include "stdafx.h"

using namespace System;

int main(array<System::String ^> ^args)//o ovome cemo kasnije tokom  tuta
{
    System::Int32 a;   //ovo je pokazatelj da se radi o objektima
    System::Int32 b;
    System::Int32 c;
    a=9;
    b=5;
    c=a+b;
Console::Write(L"Pogledajte sad ispis broja");
    Console::Write(L"  u jednom redu zbog funkcije Write()...");
    Console::WriteLine(c);  //a zbog ove funkcije kursor je u slijedecem redu!
    return 0;
}

Funkcija WriteLine() preskače u novi red ali tek nakon outputa na CMD.
No,za ovo nam je trebalo čak tri reda za ispis,znači ima bolji način koji ćemo sad pokazati:

#include "stdafx.h"

using namespace System;

int main(array<System::String ^> ^args)//o ovome cemo kasnije tokom  tuta
{
    System::Int32 a;   //ovo je pokazatelj da se radi o objektima
    System::Int32 b;
    System::Int32 c;
    a=9;
    b=5;
    c=a+b;
    Console::WriteLine((L"Ovo je sad ispis samo s jednom funk. i rezultat je : {0}",c);
    return 0;
}

 Sad vidite da je ovo ljepše.Još se malo igramo s ispisima ali i objašnjenjima.

Znači funkcija ConsoleWriteline() prima dva argumenta,prvi je riječ(string) a drugi je varijabla (objekt) ,
koji se mora na ekranu ispisati na prvom mjestu radi {0} te "naredbe" unutar riječi kao argumenta.
Općenito:

 ConsoleWriteLine("Format string",0,1,2,3,4 itd); 

Vidite kako se vrši nabrajanje mjesta izvršavanja na ekranu gdje 0(nula) znači -to ispiši prvo!Naravno pratite kako se sve odvaja,zarezima!!!

#include "stdafx.h"

using namespace System;

int main(array<System::String ^> ^args)     //o ovome cemo kasnije tokom  tuta
{
    System::Int32 a;   //ovo je pokazatelj da se radi o objektima
    System::Int32 b;
    System::Int32 c;
    a=9;
    b=5;
    c=a+b;
    Console::WriteLine((L"Ovo je sad ispis samo s jednom funk. i rezultat je :{0} a to je zbroj {1} i {2} ",c,a,b);
    return 0;
}

Vidite sad kako je sve raspoređeno i kako se vrši ispis pomoću funkcije  ConsoleWriteLine() i smještanje njenih argumenata!
Tkođer vi možete uvesti i zarez u vaš ispis ovako:
  Console::WriteLine((L"Ovo je sad ispis samo s jednom funk. i rezultat je :{0} a  to je zbroj {1:F2} i {2} ",c,a,b);
.....sad samo to zamjenite(ili dodajte) i pogledajte ispis!
F(floating point) znači da želimo zarez(decimale) a broj dva za koliko mjesta!
Sad ovako napišete kod:
Console::WriteLine((L"Ovo je sad ispis samo s jednom funk. i rezultat je :{0} a to je zbroj {1,10:F2} i {2} ",c,a,b);
    i pokrenite ....pogledajte pomak u ispisu,to je zbog broja 10 u funkciji.
Vidite sad različite načine ispisa i tokom tuta još ćemo se susretati s time tako da
i daljni napredak u tom smislu nas očekuje,zasad uvježbajte ovo gore.
Zaboravih napomenuti da dolje među slikama imate i tablicu tipova kao dio System namespace u C++/CLI-u.
__________________________________________________________________________________

 

 

Malo ćemo sad o unosu preko tipkovnice.
To radimo preko funkcije ReadLine() ;
A ispišemo to što smo napisali preko WriteLine();

#include "stdafx.h"

using namespace System;

int main(array<System::String ^> ^args)
{
    Console::WriteLine("Unesite vase ime i prezime :");
    String^ unos = Console::ReadLine();                //unos recenice
    Console::WriteLine(L"Vi se zovete ,{0} !",unos);
    Console::WriteLine();
    Console::WriteLine("Sad stisnite bilo koju tipku : \n");
    ConsoleKeyInfo stisniTipku = Console::ReadKey(true);
    Console::WriteLine(L"Tipka koju ste stisnuli odgovara :  {0,3}    slovu !\n",
        stisniTipku.KeyChar);

    return 0;
}

Ovdje vidite i funkciju ReadKey() koja nam govori što smo stisnuli.
ConsoleKeyInfo je u sastavu System namespace i "stisniTipku" je objekt tog tipa nad kojim
funkcija ReadKey() vrši radnju da li je pritisnuta i  na kraju dobivamo i ispisujemo informaciju koja je
tipka stisnuta pomoću izraza KeyChar.Iz ovog kratkog primjera vidite da uglavnom radimo s objektima.
Naravno ,zapitali ste se već o onome malome znakiću koji se dobije pritiskom
AltGr tipkom +  broj 3(kod mene)tamo gdje je hat^ , razmaknica odmah nakon toga,
to je tkz. "hat" koji referira da se radi o objektu tipa
string
što upućuje na to da program vodi računa o smještanju tog objekta u memoriju.
To je specifičnost C++/CLI programiranja i ništa se ne radi bez ^ "hat" i objekti koji su na taj način
u sigurnim rukama jer im se priljepila pratnja koja će voditi računa o njemu.Zasad toliko o tome jer će
o tome biti riječi kroz tut!
Vaše je na ovim počecima uvidjeti male posebnosti pri C++/CLI programiranju i za početak
sve ovo dobro uvježbati i ponavljati.....a to je samo početak.
Ne idem  odmah u dubinu nekih pojmova jer na ovoj razini to nije ni potrebno.

 

 

 

 

klik na file-&gt;new-&gt;project...i   eto na slici .. klik na file->new->project...i eto na slici ..
izaberete clr console app i imenujte projekt... izaberete clr console app i imenujte projekt...
ovako izgleda kad se pokaže i sad  napravite build i build solution-&gt;debug-&gt;start without debuging! ovako izgleda kad se pokaže i sad napravite build i build solution->debug->start without debuging!
...a mi ćemo ovo pisati i pokrenuti ...... ...a mi ćemo ovo pisati i pokrenuti ......
...a ovo je rezultat toga čije će objašnjenje biti u tekstu!!! ...a ovo je rezultat toga čije će objašnjenje biti u tekstu!!!
...&quot;klasni oblik tipova&quot;....&quot;objekti&quot;... ..."klasni oblik tipova"...."objekti"...
v_maxcpp
Poruka je uređivana zadnji put sri 20.8.2008 17:54 (v_maxcpp).
17 godina
neaktivan
offline
C++ tutorijali...

Poštovanje!

Evo ovako, trebao bi pomoć. Dal bi mi netko mogao riješiti sljedeća dva zadatka!

 

Zadatak 1.

 

U programskom jeziku C++ napišite program koji će:

 

1. Tražiti od korisnika da unese broj studenata n (maksimalan broj studenata je 5) te omogućiti unos n ocjena te n imena i prezimena studenata.

2. Ispisati informacije o studentima obrnutim redoslijedom od njihova unosa.

3. Ispisati informacije o studentu s najvećom ocjenom.

4. Ispisati prosjek (aritmetičku sredinu) ocjena svih studenata. Osim toga, potrebno je ispisati sve studente čija je ocjena veća od prosječne.

 

Program je potrebno realizirati pomoću izbornika.

 

 

 

Zadatak 2.

 

Napišite C++ program koji će učitavati prirodni broj N te dinamički alocirati polje tipa short duljine N. Treba učitati N brojeva, sortirati ih uzlazno, te ih ispisatu u decimalnom, oktalnom i heksadecimalnom obliku.

 

Program treba koristiti sljedeće funkcije:

 

Citaj - Funkcija tipa void kojom se učitava polje od N brojeva

Sortiraj - Funkcija kojom se sortira polje brojeva

Ispisi - Funkcija kojom se ispisuje polje od N brojeva i to u sva tri oblika.

 

Primjer:

 

Upisite N: 5

 

Upisite 1. broj: 35

Upisite 2. broj: 12

Upisite 3. broj: 44

Upisite 4. broj: 25

Upisite 5. broj: 62

 

Ispis:

Dec    Hex   Oct

12     0c      14

25     19      31

35     23      43

44     2c       54

62     3e      76

 

 

ZABRANJENO JE KORIŠTENJE GLOBALNIH VARIJABLI!

 

 

 

Eto, bio bih veoma zahvalan kad bi mi netko pomogao riješiti ova dva zadataka...

 
0 0 hvala 0
17 godina
neaktivan
offline
RE: C++ tutorijali...

Necu ti ih rjesit, nego objasnit kako da ih ti rjesis...
1. S obzirom da je N <= 5, nema potrebe sa nicim drugim osim brute forca..... to ti znaci najgluplje, najlakse i najsporije moguce rjesenje....
     Znaci, napravi si klasu OCJENA. U toj klasi, stavi si private clanove: Ime, Prezime, Ocjena (s obzirom da cemo ih koristit kao array, moras ih deklarirat kao pointere; NOTE da ako zelis pointer na tip podataka char *, dodjes na char **), te N (koji nece biti pointer, jer pokazuje koliko imamo clanova).

     Sta se tice public clanova, trebaju biti: konstruktor, dekonstruktor (ako koristis char *), te funkcije add, printr, printmax, i printavg (mozes staviti i operator[] da ispise podatak o nekom odredjenom useru, ali to ne pise u zadatku)....

    Znaci, konstruktor uzima parametar MAXN. U ovom slucaju, MAXN=5. On alocira prostor potreban da bi klasa radila, te postavlja N na 0.
        Pazi kod dinamickog alociranja char * arraya.... Moras prvo alocirati MAXN pointera, a onda za svaki pointer (ili element arraya), moras alocirati maksimalan broj slova u imenu/prezimenu.... Znaci, konstruktor bi bio:              OCJENA (int MAXN) {
             N = 0;
             ocjena = new int[MAXN];
            
             ime = new char *[MAXN];
             prezime = new char *[MAXN];
             for (int i = 0; i < MAXN; i++) {
                   ime[i] = new char[100]; //recimo da ime i prezime nece sadrzavat vise od 100 znakova
                   prezime[i] = new char[100];
             }
        }

    Dok dekonstruktor dealocira prostor alociranim konstruktorom... To takodjer moras for petljom... delete[] ime/prezime, bi izbrisalo samo array, ne njegove elementa.... Znaci, moras prvo izbrisat sve elemente, a tek onda pointer na te elemente. Kod:
~OCJENA () {
    delete [] ocjena;
    for (int i = 0; i < MAXN; i++) {
        delete [] ime[i];

        delete [] prezime[i];
   }
   delete [] ime;

   delete [] prezime;
}



    Funkcija add prima parametre: ime, prezime, ocjena. Upisuje podatke u arraye, te povecava N.
    Funkcija printr pise informacije o studentima oburtnutim redom, printmax, printa studenta sa najvisom mogucom ocijenom, dok printavg printa studente sa nadprosjecnom ocjenom.

   Printr mozes implementirati jednostavnom for petljom od N-1 do 0.....
   Printmax implementiraj petljom od 0, do N-1 u kojo zapamtis index najveceg strebera. Te, kasnije ispises njegove podatke..... To mozes jako jednostavno. Napisi si varijablu maxi. Petlju for (i, i<N), te unutra imas if koji provjerava dali je ocjena[i] > ocjena[maxi]... ako je maxi postavis na vrjednost i. I onda ispise podatke ime[maxi], prezime[maxi], ocjena[maxi];
   Printavg napravi kao for petlju od 0 do N-1 gdje imas varijablu koja zbraja ocjene svih studenta. Kasnije taj broj podjelis sa N (broj studenata) i imas prosjek.... Napravis jos jednu for petlju u kojoj pises sve ucenike koji imaju vecu ocjenu.

2.Ok, ovdje takodjer napravis klasu...
   Znaci, imas privatan clan broj (pointer). U konstruktoru primas parametar N, te alociras broj. U dekonstruktoru ga dealociras.
   Unutar te klase imas public funkcije: citaj, sortiraj i reci.
  
   citaj funkcija ima for petlju od 0 do N, te cita brojeve sa stdin-a (standardni ulaz iliti tipkovnica), tj sprema ih u array broj.
  
   sortiraj funkcija sortira podatke.... najjednostavniji i najbrzi nacin za tebe je da jednostavno ukljucis zaglavlje algorithm te koristis sort funkciju. Znaci, na vrhu programa, ispod svih linija koje pocinju sa #include, upisi #include <algorithm>.  A unutar funckije sortiraj upises sort (broj, broj+N-1);  Za vise informacija link
   
   funkcija je jednostavna.... sada kada je niz sortiran, samo odi for petljom po clanovima. Te koristi printf funkciju.... Znaci, printf ("%x", broj[i]) pise hexadekadski zapis broja broj[i], dok printf("%o", broj[i]) pise oknalni....

  
   Tesko mi je ovako objasnjavat..... Ako nesto ne kuzis, posalji mi pm, sa svojim msnom pa cu ti objasnit detaljnije....

Poruka je uređivana zadnji put pon 25.8.2008 14:55 (Jazzfan).
Nova poruka
E-mail:
Lozinka:
 
vrh stranice