świerszczyński,programowanie obiektowe,Metody wirtualne

background image

3 . M et o dy wir tu aln e . Przykł a d ilu s tr uj c y ich u yt e c z n o

.

ą

ż

ś ć

Przykład w C++

#include <iostream.h>
const float pi = 3.14159;

class Figura {
public:
virtual float pole() const { // deklaracja metody wirtualnej
return -1.0;
}
};

class Kwadrat : public Figura {
public:
Kwadrat( const float bok ) : a( bok ) {}
float pole() const {
return a * a;
}
private:
float a; // bok kwadratu
};

class Kolo : public Figura {
public:
Kolo( const float promien ) : r( promien ) {}
float pole() const {
return pi * r * r;
}
private:
float r; // promien kola
};

void wyswietlPole( Figura& figura ) {
std::cout << figura.pole() << endl;
return;
}

int main() {
// deklaracje obiektow:
Figura jakasFigura;
Kwadrat jakisKwadrat( 5 );
Kolo jakiesKolo( 3 );
Figura* wskJakasFigura = 0; // deklaracja wskaźnika

// obiekty -------------------------------
std::cout << jakasFigura.pole() << endl; // wynik: -1
std::cout << jakisKwadrat.pole() << endl; // wynik: 25

background image

std::cout << jakiesKolo.pole() << endl; // wynik: 28.274...

// wskazniki -----------------------------
wskJakasFigura = &jakasFigura;
std::cout << wskJakasFigura->pole() << endl; // wynik: -1
wskJakasFigura = &jakisKwadrat;
std::cout << wskJakasFigura->pole() << endl; // wynik: 25
wskJakasFigura = &jakiesKolo;
std::cout << wskJakasFigura->pole() << endl; // wynik: 28.274...

// referencje -----------------------------
wyswietlPole( jakasFigura ); // wynik: -1
wyswietlPole( jakisKwadrat ); // wynik: 25
wyswietlPole( jakiesKolo ); // wynik: 28.274...

return 0;
}

Wywołanie metod składowych dla każdego z obiektów powoduje wykonanie metody

odpowiedniej dla klasy danego obiektu. Następnie wskaźnikowi wskJakasFigura zostaje
przypisany adres obiektu jakasFigura i zostaje wywołana metoda float pole().
Wynikiem jest

"-1" zgodnie z treścią metody float pole() w klasie Figura. Następnie

przypisujemy wskaźnikowi adres obiektu klasy Kwadrat - możemy tak zrobić ponieważ
klasa Kwadrat jest klasą pochodną od klasy Figura - jest to tzw. rzutowanie w górę.
Wywołanie teraz metody float pole() dla wskaznika nie spowoduje wykonania metody
zgodnej z typem wskaźnika - który jest typu Figura* lecz zgodnie z aktualnie
wskazywanym obiektem, a więc wykonana zostanie metoda float pole() z klasy
Kwadrat (gdyż ostatnie przypisanie wskaźnikowi wartości przypisywało mu adres obiektu
klasy Kwadrat). Analogiczna sytuacja dzieje się gdy przypiszemy wskaźnikowi adres
obiektu klasy

Kolo.

Następnie zostaje wykonana funkcja

void

wyswietlPole(Figura&) która przyjmuje jako parametr obiekt klasy Figura przez
referencję. Tutaj również zostały wykonane odpowiednie metody dla obiektów klas
pochodnych a nie metoda zgodna z obiektem jaki jest zadeklarowany jako parametr
funkcji czyli float Figura::pole(). Takie działanie jest spowodowane przez
przyjmowanie obiektu klasy Figura przez referencję. Gdyby obiekty były przyjmowane
przez wartość (parametr bez

&) zostałaby wykonana 3 krotnie metoda float

Figura::pole() i 3 krotnie wyświetlona wartość -1.

Czysta wirtualność

Określa to, że metoda z klasy bazowej deklarująca metodę wirtualną nigdy nie

background image

powinna się wykonać. W efekcie klasa taka staje się klasą abstrakcyjną. Oznacza to tyle, iż
nie jest możliwe stworzenie obiektu tej klasy. Klasa taka służy jedynie temu, by
zdefiniować pewnego rodzaju interfejs i jest przeznaczona jedynie po to, by od niej
dziedziczyć.

Metodę czysto wirtualną w języku C++ deklaruje się tak:

class Figura {
public:
virtual float pole() = 0;
};

Taka deklaracja metody wirtualnej zmusza jednocześnie do określenia metody float
pole() na jednym z poziomów dziedziczenia. Nie jest możliwe pominięcie takiej
implementacji. Jednocześnie taka deklaracja uniemożliwia stworzenie jakiegokolwiek
obiektu klasy Figura np.: Figura mojObiekt;.

Właściwości metod wirtualnych

nie może być zadeklarowana jako statyczna (

static).

jeśli metoda wirtualna została zaimplementowana w jakimkolwiek wyższym
poziomie dziedziczenia (w szczególności w klasie bazowej całej struktury
dziedziczenia), nie jest konieczne podawanie implementacji w klasie pochodnej.

jeśli w klasie jest zadeklarowana jakakolwiek metoda wirtualna, zaleca się aby
destruktor w tej klasie również określić jako wirtualny

Java

W Javie domyślnie wszystkie metody są wirtualne. Aby jednak określić jakąś
metodę jako

niewirtualną należy zadeklarować metodę jako final.

Zastosowania

Rozszerzalność kodu. Polimorfizm umożliwia rozszerzanie nawet skompilowanych
fragmentów kodu.

Pozwala na rozszerzalność kodu również wtedy, gdy dostępna jest jedynie
skompilowana wersja klasy bazowej.

Zwalnia programistę od niepotrzebnego wysiłku.

Programista nie musi przejmować się tym, którą z klas pochodnych aktualnie
obsługuje, a jedynie tym, jakie operacje chce na tej klasie wykonać.

Programista myśli

co ma wykonać a nie jak to coś wykonać - nie musi się

przejmować szczegółami implementacyjnymi.


Document Outline


Wyszukiwarka

Podobne podstrony:
świerszczyński,programowanie obiektowe,Konstruktory i destruktory
obiektywne metody oceny postawy ciała (win 1997 2003)
Programowanie obiektowe(ćw) 1
Zadanie projekt przychodnia lekarska, Programowanie obiektowe
Programowanie obiektowe w PHP4 i PHP5 11 2005
Polimorfizm i metody wirtualne
Programowanie Obiektowe ZadTest Nieznany
Egzamin Programowanie Obiektowe Głowacki, Programowanie Obiektowe
Jezyk C Efektywne programowanie obiektowe cpefpo
Programowanie Obiektowe Ćwiczenia 5
Programowanie obiektowe(cw) 2 i Nieznany
obiekty, metody
programowanie obiektowe 05, c c++, c#
Intuicyjne podstawy programowania obiektowego0
Programowanie obiektowe, CPP program, 1
wyklad5.cpp, JAVA jest językiem programowania obiektowego
projekt01, wisisz, wydzial informatyki, studia zaoczne inzynierskie, programowanie obiektowe, projek

więcej podobnych podstron