Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

virtuelne metode

[es] :: C/C++ programiranje :: virtuelne metode

[ Pregleda: 4138 | Odgovora: 8 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

Pretender

Član broj: 12407
Poruke: 100
212.124.182.*



Profil

icon virtuelne metode08.10.2003. u 15:28 - pre 249 meseci

Code:

1:     //Listing 12.8 Using virtual methods
2:
3:     #include <iostream.h>
4:
5:     class Mammal
6:     {
7:     public:
8:        Mammal():itsAge(1) { cout << "Mammal constructor...\n"; }
9:        ~Mammal() { cout << "Mammal destructor...\n"; }
10:       void Move() const { cout << "Mammal move one step\n"; }
11:       virtual void Speak() const { cout << "Mammal speak!\n"; }
12:    protected:
13:       int itsAge;
14:
15:    };
16:
17:    class Dog : public Mammal
18:    {
19:    public:
20:       Dog() { cout << "Dog Constructor...\n"; }
21:       ~Dog() { cout << "Dog destructor...\n"; }
22:       void WagTail() { cout << "Wagging Tail...\n"; }
23:       void Speak()const { cout << "Woof!\n"; }
24:       void Move()const { cout << "Dog moves 5 steps...\n"; }
25:    };
26:
27:    int main()
28:    {
29:
30:       Mammal *pDog = new Dog;
31:       pDog->Move();
32:       pDog->Speak();
33:
34:     return 0;
35: }

Output: Mammal constructor...
Dog Constructor...
Mammal move one step
Woof!


Uvodjenje odrednice VIRTUAL, izgleda da vise dotice nevirtuelne f-je, jer bez toga normalno koristimo override u izvedenim klasama, a kada uvedemo VIRTUAL onda je override moguc samo sa virtuelnim f-jama, dok se nevirtuelne ne izvrsavaju, vec se umesto njih izvr. istoimene metode iz bazne klase.

E sad, da li je cela ova masinerija uvedena zato, da bi smo mogli da pozovemo bas bazni metod Move()(specijalno kreiranim pointerom pDog), iako imamo definisan istoimeni metod u izvedenom objektu (tj. da bi mogli da biramo izmedju base i derived metoda).
Citat:
C++ extends its polymorphism to allow pointers to base classes to be assigned to derived class objects.

Ali sta ako hocemo bazni Speak() metod? Njega smo (zato sto je virtuelan) overrideom sakrili , i sad iz izvedene klase, njemu nemamo pristup.
Znaci, ako bazni metod proglasimo za VIRTUAL ne mozemo mu vise pristupiti iz izvedene klase.

Dakle, o cemu se radi ?


Hvala







 
Odgovor na temu

Dragi Tata
Malo ispod Kanade

Član broj: 1958
Poruke: 3906
199.171.112.*



+6 Profil

icon Re: virtuelne metode08.10.2003. u 16:34 - pre 249 meseci
Nisam baš najbolje razumeo šta pitaš, ali da objasnim ukratko šta je suština kod virtuelnih funkcija: One su zamena za ovakve konstrukcije:

Code:

void Speak(Mammal* mammal)
{
switch (mammal->GetType()) 
  {
  case DOG:
  cout << "Woof!\n"; 
  break;
  case CAT:
  cout << "Meow\n";
  break;
  default:
  "Mammal speak!\n"; 
  break;
  }
}




 
Odgovor na temu

filmil
Filip Miletić
Oce Technologies B.V., inženjer
hardvera
Arcen, NL

Član broj: 243
Poruke: 2114
*.et.tudelft.nl

Jabber: filmil@jabber.org
ICQ: 36601391


+3 Profil

icon Re: virtuelne metode08.10.2003. u 16:40 - pre 249 meseci
Citat:
Pretender:
E sad, da li je cela ova masinerija uvedena zato, da bi smo mogli da pozovemo bas bazni metod Move()(specijalno kreiranim pointerom pDog), iako imamo definisan
...
Znaci, ako bazni metod proglasimo za VIRTUAL ne mozemo mu vise pristupiti iz izvedene klase.


Prva stvar: tata objasnio čemu služe virtuelne funkcije. Virtuelni mehanizam elegantno omogućava i mnoge druge lepe stvari koje se iz primera ne vide na prvi pogled. Mašinerija virtuelnih funkcija je uvedena zbog virtuelnih funkcija a ne zbog ne-virtuelnih, tj. ponašanje o kom govoriš je default kada nema v.f. V.f. služe da bi mogao elegantno da „podmetneš“ novonapisanu funkciju umesto fje iz bazne klase.

Druga stvar: Dovoljno je da uradiš: Mammal::Speak() i sve okej.
 
Odgovor na temu

Pretender

Član broj: 12407
Poruke: 100
212.124.182.*



Profil

icon Re: virtuelne metode08.10.2003. u 19:19 - pre 249 meseci
Da, taj poziv baznog metoda sam smetnuo.

Sorry ako je pitanje glupo, ali novonapisanu f-ju umesto one iz bazne klase mogu isto tako da "podmetnem" prostim overrideom a da nista ne proglasavam virtuelnim (?)

Inace ona konstrukcija koju je naveo DT, izgleda prilicno jednostavna; ne vidim sta bi tu virtuelna f-ja mogla da pojednostavi.(?)

thx
 
Odgovor na temu

Dragi Tata
Malo ispod Kanade

Član broj: 1958
Poruke: 3906
199.171.112.*



+6 Profil

icon Re: virtuelne metode08.10.2003. u 19:56 - pre 249 meseci
Citat:
Pretender:
Sorry ako je pitanje glupo, ali novonapisanu f-ju umesto one iz bazne klase mogu isto tako da "podmetnem" prostim overrideom a da nista ne proglasavam virtuelnim (?)


Jok. Pogledaj onaj tvoj primer.

Code:

pDog->Move();


Rezultuje:

Mammal move one step

Da je funkcija Move bila virtuelna, rezultat bi bio:

Dog moves 5 steps...

Dakle, kad je funkcija virtuelna, onda se izvriši nešto kao onaj switch-case koji sam dao kao ilustraciju, pa onda program "zna" da pDog u stvari pokazuje na objekat tipa Dog, iako je deklarisan kao pointer na Mammal. Ako funkcija nije virtuelna, onda nema takve provere i uvek se zove funkcija Mammal::Move, bez obzira što je objekat u stvari tipa Dog.
 
Odgovor na temu

Pretender

Član broj: 12407
Poruke: 100
212.124.182.*



Profil

icon Re: virtuelne metode08.10.2003. u 20:52 - pre 249 meseci
Pa da, ali bas to i jeste problem.

U prethodnom primeru overridinga stoji:
Code:

6:     class Mammal
7:     {
8:     public:
9:        // constructors
10:       Mammal() { cout << "Mammal constructor...\n"; }
11:       ~Mammal() { cout << "Mammal destructor...\n"; }
12:
13:       //Other methods
14:       void Speak()const { cout << "Mammal sound!\n"; }
15:       void Sleep()const { cout << "shhh. I'm sleeping.\n"; }

23:    class Dog : public Mammal
24:    {
25:    public:
26:
27:       // Constructors
28:       Dog(){ cout << "Dog constructor...\n"; }
29:       ~Dog(){ cout << "Dog destructor...\n"; }
30:
31:       // Other methods
32:       void WagTail() { cout << "Tail wagging...\n"; }
33:       void BegForFood() { cout << "Begging for food...\n"; }
34:       void Speak()const { cout << "Woof!\n"; }

i bez problema se izvrsava:
Code:

43:       Dog fido;

45:       fido.Speak();

Output: Woof!


dakle iako f-ja Speak() nije virtuelna, dobilo se ono sto se zelelo, overrideom.
I bilo koji drugi izvedeni objekat (Cat, Horse itd.) bi tako pozvao svoju f-ju Speak()

Zato ja ne vidim sta nam tu virtual pomaze.

Ispada (naravno `virtuelno`) da nam samo smeta, u slucaju, kao sto je ovaj sto si naveo, kada su neke f-je virtual a neke ne; pa onda one koje nisu v. `ni krive ni duzne` ne mogu da koriste override (slucaj sa gornjom f-jom Move()), sto bi inace mogle da komsinica nije virtual.

thx
 
Odgovor na temu

Dragi Tata
Malo ispod Kanade

Član broj: 1958
Poruke: 3906
199.171.112.*



+6 Profil

icon Re: virtuelne metode08.10.2003. u 21:23 - pre 249 meseci
pDog je deklarisan kao pointer na Mammal:

Code:

Mammal *pDog = new Dog;


a pDog->Speak() ipak zove Dog::Speak(), a ne Mammal::Speak(). U tome je "magija" virtuelnih funkcija.

U drugom primeru, fido je deklarisan kao Dog, pa će fido.Speak() naravno da pozove Dog::Speak(). Nema magije :)
 
Odgovor na temu

filmil
Filip Miletić
Oce Technologies B.V., inženjer
hardvera
Arcen, NL

Član broj: 243
Poruke: 2114
*.adsl.zonnet.nl

Jabber: filmil@jabber.org
ICQ: 36601391


+3 Profil

icon Re: virtuelne metode08.10.2003. u 21:32 - pre 249 meseci
Citat:
Pretender:
Zato ja ne vidim sta nam tu virtual pomaze.

Ispada (naravno `virtuelno`) da nam samo smeta


Samo jedna finesa te deli od razumevanja mehanizma.

Prvo:
Code:

Dog someDog;
Mammal *someMammal;

...

someMammal = &someDog;

...

someMammal->speak(); /* dobije se Woof! iako je pozvana metoda klase Mammal!!! */


Drugo:
Code:

Dog someDog;
someDog.speak(); /* dobije se Woof! Naravno. */



Finesa je sledeća. Nije poenta to što kada u drugom primeru instanciraš klasu tipa Dog dobiješ odgovor Woof, već to što u prvom primeru pozoveš funkciju speak() klase Mammal a nekom magijom izvrši se funkcija speak klase Dog iako (pazi sad) u promenljivoj someMammal ne stoji nikakva informacija koja odaje da taj pointer pokazuje na objekat klase Dog a ne na neki objekat klase Mammal. Međutim ipak se poziva ispravna funkcija.

Šta je posledica? Pa možemo napraviti nešto poput:

Code:

class Cat : public Mammal ...
class Whale: public Mammal ...
class Dolphin: public Mammal...
class Platypus: public Mammal...


zatim da instanciramo promenljive svih tih tipova i sve ih strpamo u niz mammal_array a onda uradimo sledeće:

Code:

for(int i=0; i < max_mammals; ++i) 
     mammal_array[i]->speak();


Zahvaljujući virtuelnom mehanizmu iako kod za sve članove niza izgleda potpuno isto, ipak će se za svaki pojedinačni objekat iz niza mammal_array izvršiti tačno ona funkcija speak() koja odgovara objektu koji se zaista krije ispod odgovarajućeg pointera iako sam program pojma nema da smo u isti niz zapravo potrpali objekte različitih tipova! To nam omogućava da pišemo programe koji operišu nad podacima nekog tipa, ne razmišljajući o tome koji je to tip zapravo: gornji kod će raditi i kada za 100 godina evolucija i černobilski sindrom iznedre novu vrstu DvoglavogDelfina (izvedenog iz klase Mammal) a mi napišemo odgovarajuću klasu — i to dokle god u definiciji DvoglavogDelfina postoji funkcija speak(), makar DvoglaviDelfin govorio „Živeo Fidel Kastro“ (ili RMS, svejedno:) ). Stručnije rečeno: dokle god DvoglaviDelfin implementira isti interfejs. [u vezi interfejsa moram reći da sam neke detalje zanemario, u nadi da ćemo o tom potom pričati. Za sada je bitno da razumeš gornji primer i njegovu važnost.]

f
 
Odgovor na temu

Pretender

Član broj: 12407
Poruke: 100
212.124.182.*



Profil

icon Re: virtuelne metode08.10.2003. u 22:36 - pre 249 meseci
Sve OK

Hvala tandemu.

 
Odgovor na temu

[es] :: C/C++ programiranje :: virtuelne metode

[ Pregleda: 4138 | Odgovora: 8 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.