Informatyka 2 Politechnika Białostocka - Wydział Elektryczny Elektrotechnika, semestr III, studia niestacjonarne I stopnia Rok akademicki 2012/2013 Wykład nr 6 (07.12.2012) dr inż. Jarosław Forenc
Rok akademicki 2012/2013, Wykład nr 6 2/17 Plan wykładu nr 6 Programowanie obiektowe w języku C++ dziedziczenie polimorfizm, funkcje wirtualne
Rok akademicki 2012/2013, Wykład nr 6 3/17 Dziedziczenie dziedziczenie jest to technika pozwalającą na definiowanie nowej klasy przy wykorzystaniu klasy już istniejącej polega na przejmowaniu jednej klasy (bazowej, podstawowej) przez inną klasę (pochodną) przy dziedziczeniu, w skład obiektów klasy pochodnej automatycznie wchodzą pola klasy bazowej do obiektów klasy pochodnej możemy stosować operacje zdefiniowane przez funkcje składowe klasy bazowej
Rok akademicki 2012/2013, Wykład nr 6 4/17 Dziedziczenie przykładowa klasa podstawowa i klasa pochodna /* klasa podstawowa */ class osoba char *imie; char *nazwisko; int wiek; public: osoba(char *i,char *n,int w); ~osoba() void drukuj(); ; /* klasa pochodna */ class student : public osoba char *wydzial; int semestr; public: student(char *i,char *n, int w,char *wy,int s); ~student() void drukuj(); void promocja(); ;
Rok akademicki 2012/2013, Wykład nr 6 5/17 Dziedziczenie w klasie pochodnej można zdefiniować: dodatkowe dane składowe dodatkowe funkcje składowe dane i funkcje o takich samych nazwach jak w klasie podstawowej (dane i funkcje z klasy podstawowej są zasłaniane) jeśli nie podamy sposobu dziedziczenia, to domyślnie będzie to private
Rok akademicki 2012/2013, Wykład nr 6 6/17 Dziedziczenie - sposoby dziedziczenia sposób dziedziczenia klasa podstawowa private protected public private - - - protected private protected protected public private protected public podczas dziedziczenia nie są dziedziczone: konstruktor, destruktor i operator przypisania "=" Przykład: student st1("jan","kos",20,"we",2); st1.drukuj(); st1.osoba::drukuj(); - deklaracja obiektu - wywołanie funkcji z klasy student - wywołanie funkcji z klasy osoba możliwe jest dziedziczenie wielokrotne, tzn. klasa pochodna może być klasą podstawową dla innej klasy
Rok akademicki 2012/2013, Wykład nr 6 7/17 Przykład nr 1 - dziedziczenie (1/4) #include <iostream> #include <cstring> using namespace std; class osoba private: char *imie; char *nazwisko; int wiek; public: osoba(char*,char*,int); ~osoba(); void drukuj(); ; class student : public osoba private: char *wydzial; int semestr; public: student(char*,char*,int, char*,int); ~student(); void drukuj(); void promocja(); ; klasa podstawowa (bazowa) klasa pochodna
Rok akademicki 2012/2013, Wykład nr 6 8/17 Przykład nr 1 - dziedziczenie (2/4) osoba::osoba(char *i, char *n, int w) imie = new char[strlen(i)+1]; nazwisko = new char[strlen(n)+1]; strcpy(imie,i); strcpy(nazwisko,n); wiek = w; osoba::~osoba() delete [] imie; delete [] nazwisko; void osoba::drukuj() cout << imie << " " << nazwisko; cout << " " << wiek << endl; destruktor klasy osoba konstruktor klasy osoba
Rok akademicki 2012/2013, Wykład nr 6 9/17 Przykład nr 1 - dziedziczenie (3/4) student::student(char *i,char *n,int w,char *wy,int s) : osoba(i,n,w) wydzial = new char[strlen(wy)+1]; strcpy(wydzial,wy); semestr = s; student::~student() delete [] wydzial; konstruktor klasy student void student::drukuj() osoba::drukuj(); cout << "Wydzial: " << wydzial; cout << " Semestr: " << semestr << endl; destruktor klasy student lista inicjalizacyjna konstruktora klasy student zawierająca wywołanie konstruktora klasy podstawowej (osoba)
Rok akademicki 2012/2013, Wykład nr 6 10/17 Przykład nr 1 - dziedziczenie (4/4) void student::promocja() semestr++; int main() student st1("jan","kowalski",20,"we",2); st1.drukuj(); st1.promocja(); st1.drukuj(); st1.osoba::drukuj(); jako pierwszy zostanie wywołany konstruktor klasy podstawowej (osoba) a po nim konstruktor klasy pochodnej (student) kolejność wywołania destruktorów jest odwrotna w stosunku do konstruktorów - jako pierwszy jest wywoływany destruktor klasy student, a po nim destruktor klasy osoba
Rok akademicki 2012/2013, Wykład nr 6 11/17 Przykład nr 1 - dziedziczenie (4/4) void student::promocja() Jan Kowalski 20 jako pierwszy Wydzial: zostanie wywołany WE Semestr: 2 semestr++; konstruktor Jan klasy Kowalski podstawowej 20 (osoba) a po Wydzial: nim konstruktor WE Semestr: klasy 3 pochodnej Jan Kowalski (student) 20 int main() student st1("jan","kowalski",20,"we",2); st1.drukuj(); st1.promocja(); st1.drukuj(); st1.osoba::drukuj(); kolejność wywołania destruktorów jest odwrotna w stosunku do konstruktorów - jako pierwszy jest wywoływany destruktor klasy student, a po nim destruktor klasy osoba
Rok akademicki 2012/2013, Wykład nr 6 12/17 Funkcje wirtualne (polimorfizm) Przykład: załóżmy, że piszemy program wyświetlający na ekranie różne figury (kwadrat, trójkąt, koło) do wyświetlenia każdej figury stosowana jest oddzielna funkcja, figury powinny być wyświetlane na ekranie w określonej kolejności Problem: Rozwiązanie: jak zorganizować przechowywanie informacji o figurach? jak zorganizować wyświetlanie figur? klasy + dziedziczenie + funkcje wirtualne definiujemy klasę podstawową (figura) oraz trzy klasy pochodne (kwadrat, trojkat, kolo) w klasie podstawowej umieszczamy funkcję void rysuj() poprzedzoną słowem virtual (funkcja ta nic nie robi) w klasach pochodnych umieszczamy funkcje o takich samych nazwach jak w klasie podstawowej - void rysuj() wyświetlające poszczególne figury
Rok akademicki 2012/2013, Wykład nr 6 13/17 Przykład nr 2 - funkcje wirtualne (1/3) #include <iostream> using namespace std; class figura public: virtual void rysuj() ; ; klasa podstawowa figura funkcja wirtualna rysuj()
Rok akademicki 2012/2013, Wykład nr 6 14/17 Przykład nr 2 - funkcje wirtualne (2/3) class kwadrat : public figura klasa pochodna kwadrat public: void rysuj() cout << "Kwadrat" << endl; ; class trojkat : public figura klasa pochodna trojkat public: void rysuj() cout << "Trojkat" << endl; ; class kolo : public figura klasa pochodna kolo public: void rysuj() cout << "Kolo" << endl; ;
Rok akademicki 2012/2013, Wykład nr 6 15/17 Funkcje wirtualne (polimorfizm) jeśli wskaźnikowi do klasy podstawowej (figura) przypiszemy adres obiektu klasy pochodnej (kwadrat, trojkat, kolo), to wywołując poprzez wskaźnik funkcję rysuj(), wywołamy funkcję odpowiadającą danemu obiektowi, np. figura *ptr; kwadrat kw1; trojkat tr1; kolo kol1; ptr = &kw1; ptr->rysuj(); ptr = &tr1; ptr->rysuj(); ptr = &kol1; ptr->rysuj(); - deklaracja wskaźnika do obiektu klasy figura - deklaracja obiektu klasy kwadrat - deklaracja obiektu klasy trojkat - deklaracja obiektu klasy kolo - wywołana zostanie funkcja rysuj() z klasy kwadrat - wywołana zostanie funkcja rysuj() z klasy trojkat - wywołana zostanie funkcja rysuj() z klasy kolo mówimy, że w powyższym przykładzie wystąpił polimorfizm (wielopostaciowość)
Rok akademicki 2012/2013, Wykład nr 6 16/17 Przykład nr 2 - funkcje wirtualne (3/3) int main() kwadrat kwadrat1, kwadrat2; trojkat trojkat1, trojkat2; kolo kolo1, kolo2; figura *lista[6]; Trojkat Kwadrat Kolo Kwadrat Kolo Trojkat lista[0] = &trojkat1; lista[1] = &kwadrat1; lista[2] = &kolo1; lista[3] = &kwadrat2; lista[4] = &kolo2; lista[5] = &trojkat2; for (int i=0; i<6; i++) lista[i]->rysuj();
Rok akademicki 2012/2013, Wykład nr 6 17/17 Koniec wykładu nr 6 Dziękuję za uwagę!