Funkcje wirtualne

virus1441
Artykuł został umieszczony na liście Zalążków artykułów. Jeżeli możesz rozbuduj go!

Funkcje wirtualne są związane z mechanizmem polimorfizmu. Przykładowo:

#include <iostream>
 
class Figura
{
public:
    void Wyswietl ();
};
 
class Kwadrat : public Figura
{
public:
    void Wyswietl ();
};
 
class Kolo : public Figura
{
public:
    void Wyswietl ();
};
 
void Figura::Wyswietl ()
{
    cout << "Figura" << endl;
}
 
void Kwadrat::Wyswietl ()
{
    cout << "Kwadrat" << endl;
}
 
void Kolo::Wyswietl ()
{
    cout << "Kolo" << endl;
}
 
int main(int argc, char *argv[])
{
    Figura figura;
    Kwadrat kwadrat;
    Kolo kolo;
 
    cout << "Wywolania funkcji na rzecz obiektow" << endl;
 
    figura.Wyswietl();
    kwadrat.Wyswietl();
    kolo.Wyswietl();
 
    Figura *wsk;
 
    cout << "Wywolanie funkcji przez wskaznik typu Figura wskazujacy na obiekt typu Figura" << endl;
 
    wsk = &figura;
    wsk->Wyswietl();
 
    cout << "Wywolania funkcji przez wskaznik typu Figura wskazujacy na obiekty dziedziczace po Figirze" << endl;
 
    wsk = &kwadrat;
    wsk->Wyswietl();
 
    wsk = &kolo;
    wsk->Wyswietl();
 
    return 0;
}

Wynik tego kodu to:

Wywołania funkcji na rzecz obiektów Figura Kwadrat Kolo Wywołanie funkcji przez wskaźnik typu Figura wskazujący na obiekt typu Figura Figura Wywołania funkcji przez wskaźnik typu Figura wskazujący na obiekty dziedziczące po Figurze Figura Figura

Wynik wywołań na rzecz obiektów, i przez wskaźnik na obiekt typu podstawowego nie dziwią. Natomiast wywołanie przez wskaźnik typu Figura obiektu typu Kwadrat wyświetliło napis "Figura". Kompilator zachował się prawidłowo, ponieważ wskaźnik był typu Figura, więc została wywołana funkcja właściwa dla tego typu. Można go jednak zmusić, aby zachował się inaczej. Jeśli w deklaracji klasy podstawowej dodamy słowo virtual

class Figura
{
public:
    void virtual Wyswietl ();
};

efekt będzie następujący:

(...) Wywołanie funkcji przez wskaźnik typu Figura wskazujący na obiekt typu Figura Figura Wywołania funkcji przez wskaźnik typu Figura wskazujący na obiekty dziedziczące po Figurze Kwadrat Kolo

Mimo iż wskaźnik jest typu Figura, kompilator widząc, że funkcja jest funkcją wirtualną sprawdził na jaki typ rzeczywiście wskazuje wskaźnik. Gdy zobaczył, że jest to Kwadrat wykonał funkcje z tej klasy, gdy zobaczył, że ma do czynienia z kołem wykonał funkcje właściwą dla Koła.

Zobacz też:

7 komentarzy

Pff, jakoś nie widze, żeby to było napisane. Nie widze też w kodzie fragmentu:

virtual float pole() = 0;

A może mam problemy ze wzrokiem ?

Główną rolą funkcji virtualnych są wywołania polimorficzne i o tym powinieneś napisać. A ty napisałeś o tym jak zrobić klasę abstakcyjną. Nie możliwe jest utworzenie obiektu tylko gdy ma metodę czysto virtualną, a nie funkcje składowe virtualne - odróżniaj pojęcia :/ To co jest teraz w arcie powinno być na jego końcu, po polimorfizmie.

Ciekawe jak potem ma nie być pytań na forum jak tu takie bzdury są wypisywane...

W końcu ktoś to poprawił :)

Całkowicie zmieniłem artykuł, teraz dotyczy funkcji wirtualnych a nie klas abstrakcyjnych (poprzedniemu autorowi najwyraźniej pomyliły się pojęcia). Ale jako że temat jest bardzo szeroki a streściłem go w jednym przykładzie daje to jako zalążek. Przyznajcie że lepszy zalążek niż bzdura..

@DzieX: Jak czytamy w wikipedii (http://pl.wikipedia.org/wiki/Klasa_abstrakcyjna):
"W C++ klasą abstrakcyjną jest klasa, która posiada zadeklarowaną co najmniej jedną metodę czysto wirtualną."
A wcześniej (na tej samej stronie):
"Klasa abstrakcyjna jest pewnym uogólnieniem innych klas (na przykład dla występujących w rzeczywistości obiektów), lecz sama jako taka nie istnieje."
Z czego wynika, że klasa z funkcjami wirtualnymi nie może powstać, gdyż "sama jako taka nie istnieje". A może ja po polsku nie rozumiem?

Ten artykuł jest chyba do poprawy. Jak to nie mogą powstawać? Doczytaj najpierw co to jest, a potem o tym pisz.

Racja, twoja wersja jest czytelniejsza :) Muszę jeszcze nad ort. popracować :P

virus: fajnie by było, gdybyś zaczął redagować swoje teksty w sposób analogiczny do tego, który teraz poprawiłem :)