Tematyka wykładów 1. Wprowadzenie. Klasy cz. 1 - Język C++. Programowanie obiektowe - Klasy i obiekty - Budowa i deklaracja klasy. Prawa dostępu - Pola i funkcje składowe - Konstruktor i destruktor - Tworzenie obiektów 2. Klasy cz. 2 - Konstruktor kopiujący. Pola tworzone statycznie i dynamicznie - Funkcje zaprzyjaźnione - Składowe statyczne 3. Funkcje operatorowe. Wskaźnik this 4. Dziedziczenie 5. Polimorfizm i funkcje wirtualne 6. Szablony 7. Strumienie 8. Tworzenie aplikacji w systemie Windows
Dziedziczenie Wprowadzenie (co to jest? po co? idea?) Klasa bazowa i pochodna Rodzaje dziedziczenia Definiowanie klasy pochodnej Właściwości dziedziczenia Dziedziczenie publiczne i prywatne Obiekt klasy pochodnej Przesłanianie identyfikatorów
Paradygmaty PO Celem programowania obiektowego (PO) jest ograniczenie problemu złożoności programowania poprzez hermetyzację danych oraz wiązanie obiektów w hierarchiczne struktury. Hermetyzacja danych Hierarchia klas (obiektów)
Idea dziedziczenia ObiektGraficzny kolor linii rodzaj linii grubość linii kolor wypełnienia NIEOKREŚLONY KSZTAŁT OKREŚLONY KSZTAŁT OKREŚLONA METODA RYSOWANIA OKREŚLONY KSZTAŁT NIEOKREŚLONA METODA RYSOWANIA Linia łamana P 1 P 2 P 3 P 4 P 5 P 1 Trójkąt P 2 P 3 KształtProstokątny P 1 P 2 P 1, P 2,..., P n P 1, P 2, P 3 P 1, P 2 OKREŚLONA METODA RYSOWANIA P 1 Linia Prostokąt P 1 P 1 Elipsa P 2 P 2 P 2 Hierarchia klas: od klas bardziej ogólnych do klas szczegółowych.
Dziedziczenie - definicja Dziedziczenie to mechanizm tworzenia nowej klasy w oparciu o klasę wcześniej zdefiniowaną. Nowa klasa (klasa pochodna) nie musi być definiowana od podstaw może korzystać z pól i metod klasy już zdefiniowanej (klasy bazowej). Klasa pochodna to rozszerzenie klasy bazowej. Ważna właściwość: do tworzenia klasy pochodnej nie jest potrzebny dostęp do kodu źródłowego klasy bazowej wystarczy interfejs i kod binarny klasy (przykład: wykorzystanie bibliotek MFC, VCL itp.).
Dziedziczenie jednobazowe Klasa bazowa Klasa pochodna Klasa bazowa Klasa bazowa Klasa pochodna 1 Klasa pochodna 2 Klasa pochodna 1 Klasa pochodna 2
Dziedziczenie wielobazowe Klasa bazowa 1 Klasa bazowa 2 Klasa pochodna Problem: składowe o tych samych nazwach w klasach bazowych. Rozwiązanie: odwołanie za pomocą nazwy kwalifikowanej <nazwa_klasy> :: <nazwa_skladowej> x A B x C A::x B::x
Definiowanie klasy pochodnej class <KlasaPochodna> : <SposobDziedzicz> <KlasaBazowa> public private protected PRZYKŁAD: class Lokalizacja // klasa bazowa < deklaracje i definicje > class Punkt : public Lokalizacja < deklaracje i definicje > // klasa pochodna
Właściwości dziedziczenia Co może być dziedziczone? funkcje składowe (metody) pola składowe Nie wszystkie! W zależności od kwalifikatora dostępu. Co nie jest dziedziczone? konstruktory destruktory funkcje zaprzyjaźnione (zaprzyjaźnienia) funkcja operatorowa operator = Pola statyczne są wspólne dla wszystkich obiektów wszystkich dziedziczących je klas (wspólne dla całej rodziny klas).
Prawa dostępu Kwalifikatory: public, protected, private Wszystkie składowe zdefiniowane w klasie są dostępne wewnątrz klasy. Składowe publiczne (public) są dostępne tam, gdzie dostępna jest klasa i są dziedziczone przez klasy pochodne. Składowe prywatne (private) są dostępne tylko w danej klasie. Składowe chronione (protected) są dostępne we wszystkich klasach pochodnych.
Sposoby dziedziczenia Dziedziczenie publiczne: public Składowe publiczne klasy bazowej są dostępne jako składowe publiczne w klasie pochodnej Składowe zabezpieczone klasy bazowej są dostępne jako składowe zabezpieczone w klasie pochodnej Składowe prywatne nie są dziedziczone Dziedziczenie prywatne: private Składowe publiczne i zabezpieczone są dostępne jako składowe prywatne w klasie pochodnej Składowe prywatne nie są dziedziczone Dziedziczenie publiczne rozszerzanie możliwości klasy bazowej. Dziedziczenie prywatne klasy bazowe to klasy robocze, wewnętrzne z punktu widzenia funkcjonalności, a klasy pochodne są finalne.
Warianty dziedziczenia Składowe widoczne na zewnątrz klasy class B : public A pubb, puba protected: prob, proa private: prib class A puba protected: proa private: pria class D : protected A pubd protected: prod, puba, proa private: prid class C : private A pubc protected: proc private: pric, puba, proa
Warianty dziedziczenia Składowe widoczne na zewnątrz klasy class B : public A pubb, puba protected: prob, proa private: prib class A puba protected: proa private: pria class C : private A pubc protected: proc private: pric, puba, proa
Obiekt klasy pochodnej Utworzenie obiektu klasy pochodnej jest poprzedzone utworzeniem obiektu klasy bazowej. Konstruktor klasy pochodnej najpierw wywołuje konstruktor klasy bazowej, a następnie realizuje swoje zadania. Jeżeli klasa bazowa ma kilka konstruktorów, należy wskazać przy użyciu listy inicjalizującej, który z konstruktorów ma zostać wywołany. Kiedy brak tej informacji, zawsze wywoływany jest konstruktor bezparametrowy. Przykład: ABCD.cpp
class A A() } A(int x) } class B: public A B() } B(int b) : A(b) } B(float x) } Przykład: ABCD.cpp Konstruktory: wywoływane są zgodnie z hierarchią klas. Destruktory: wywoływane są w odwrotnej kolejności. Lista inicjalizująca: wywołanie wybranego konstruktora z klasy bazowej A HIERARCHIA KLAS A B public private public C D class C: public B class D: private B C() } D() } C B A D
Przesłanianie identyfikatorów Jeżeli w klasie pochodnej zdefiniowana jest składowa o takiej samej nazwie jak w klasie bazowej, to następuje przesłonięcie (nie przedefiniowanie) odziedziczonej składowej. W przypadku funkcji, przesłonięcie ma miejsce nawet wtedy, gdy funkcje mają różne argumenty. Przesłonięta składowa jest nadal dostępna w klasie pochodnej przez nazwę kwalifikowaną. Zasady poszukiwania składowych: 1. Nazwa składowej poszukiwana jest w klasie bieżącej (określonej przez typ obiektu). 2. Jeżeli nie zostanie znaleziona, nazwa składowej jest poszukiwana w kolejnych klasach bazowych (kolejno, idąc w górę hierarchii klas).