Wprowadzenie do programowanie obiektowego w języku C++



Podobne dokumenty
Programowanie w języku C++

Dziedziczenie. Ogólna postać dziedziczenia klas:

Programowanie obiektowe w języku

Programowanie obiektowe Wykład 6. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14

Mechanizm dziedziczenia

TEMAT : KLASY DZIEDZICZENIE

> C++ dziedziczenie. Dane: Iwona Polak. Uniwersytet Śląski Instytut Informatyki

Programowanie w języku C++

Wprowadzenie do programowanie obiektowego w języku C++

Wstęp do programowania obiektowego. WYKŁAD 3 Dziedziczenie Pola i funkcje statyczne Funkcje zaprzyjaźnione, this

Podstawy programowania w języku C++

Zaawansowane programowanie w języku C++ Programowanie obiektowe

C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie C++ - DZIEDZICZENIE.

PARADYGMATY PROGRAMOWANIA Wykład 4

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 4. Karol Tarnowski A-1 p.

dr inż. Jarosław Forenc

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

Wykład 8: klasy cz. 4

PARADYGMATY PROGRAMOWANIA Wykład 2

Wykład 5: Klasy cz. 3

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016

Programowanie w C++ Wykład 13. Katarzyna Grzelak. 4 czerwca K.Grzelak (Wykład 13) Programowanie w C++ 1 / 26

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Techniki programowania INP001002Wl rok akademicki 2017/18 semestr letni. Wykład 4. Karol Tarnowski A-1 p.

Programowanie Obiektowe i C++

Programowanie obiektowe, wykład nr 6. Klasy i obiekty

Programowanie obiektowe Wykład 7. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/20

Mechanizm dziedziczenia

Programowanie w C++ Wykład 14. Katarzyna Grzelak. 3 czerwca K.Grzelak (Wykład 14) Programowanie w C++ 1 / 27

Materiały do zajęć VII

Zaawansowane programowanie w C++ (PCP)

2. Klasy cz. 2 - Konstruktor kopiujący. Pola tworzone statycznie i dynamicznie - Funkcje zaprzyjaźnione - Składowe statyczne

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

Dziedziczenie & W slajdach są materiały zapożyczone z

Dziedziczenie. Streszczenie Celem wykładu jest omówienie tematyki dziedziczenia klas. Czas wykładu 45 minut.

Programowanie 2. Język C++. Wykład 3.

Wykład V. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Programowanie obiektowe

Programowanie obiektowe w C++ Wykład 12

Zaawansowane programowanie w języku C++ Klasy w C++

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Podstawy programowania w języku C++

Język C++ Programowanie obiektowe

Programowanie współbieżne Wykład 8 Podstawy programowania obiektowego. Iwona Kochaoska

2.4 Dziedziczenie. 2.4 Dziedziczenie Przykłady programowania w C - kurs podstawowy

class Student Deklaracja klasy Osoba: Deklaracja klasy Student:

Podstawy programowania w języku C++

1 Dziedziczenie. 1.1 Koncepcja dziedziczenia. Ćwiczenie 3

Wykład 4: Klasy i Metody

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Dziedziczenie jednobazowe, poliformizm

Programowanie 2. Język C++. Wykład 9.

Projektowanie obiektowe. Roman Simiński Polimorfizm

Język C++ wykład VII. uzupełnienie notatek: dr Jerzy Białkowski. Programowanie C/C++ Język C++ wykład VII. dr Jarosław Mederski. Spis.

Języki Programowania. Prowadząca: dr inż. Hanna Zbroszczyk. tel: Konsultacje: piątek:

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie?

Wprowadzenie do szablonów szablony funkcji

Wprowadzenie do szablonów szablony funkcji

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

Typy zmiennych proste i złożone. Programowanie komputerów. Tablica. Złożone typy zmiennych. Klasa. Struktura

Podstawy programowania w języku C++

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

Szablony funkcji i szablony klas

Zaawansowane programowanie w C++ (PCP)

Informatyka I. Dziedziczenie. Nadpisanie metod. Klasy abstrakcyjne. Wskaźnik this. Metody i pola statyczne. dr inż. Andrzej Czerepicki

Programowanie obiektowe

Wprowadzenie w dziedziczenie. Klasa D dziedziczy klasę B: Klasa B klasa bazowa (base class), klasa D klasa pochodna (derived class).

Języki i techniki programowania Ćwiczenia 3 Dziedziczenie

Programowanie obiektowe

PROGRAMOWANIE OBIEKTOWE W C++ cz. 2. Dziedziczenie, operacje wej cia-wyj cia, przeładowanie operatorów.

Programowanie w C++ Wykład 12. Katarzyna Grzelak. 20 maja K.Grzelak (Wykład 12) Programowanie w C++ 1 / 32

Konstruktory. Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut.

C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm POLIMORFIZM

Klasa dziedzicząca posiada wszystkie cechy klasy bazowej (plus swoje własne) dodawanie nowego kodu bez edycji (i ewentualnego wprowadzania

Wykład 1. Program przedmiotu. Programowanie Obiektowe (język C++) Literatura. Program przedmiotu c.d.:

Programowanie, część I

Programowanie obiektowe w języku C++ Zarządzanie procesami. dr inż. Jarosław Forenc. Przeładowanie (przeciążanie) operatorów

EGZAMIN 2 (14 WRZEŚNIA 2015) JĘZYK C++

Programowanie obiektowe Wykład 3. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21

Język C++ wykład VI. uzupełnienie notatek: dr Jerzy Białkowski. Programowanie C/C++ Język C++ wykład VI. dr Jarosław Mederski.

TEMAT : KLASY POLIMORFIZM

Referencje do zmiennych i obiektów

C++ - [4-7] Polimorfizm

Dziedziczenie. dr Jarosław Skaruz

Java: kilka brakujących szczegółów i uniwersalna nadklasa Object

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 12

Aplikacje w środowisku Java

Programowanie obiektowe w języku C++

Podstawy Programowania Obiektowego

Kurs programowania. Wstęp - wykład 0. Wojciech Macyna. 22 lutego 2016

Podstawy programowania w języku C i C++

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy KONSTRUKTORY

Podstawy programowania

Programowanie obiektowe w C++ Wykład 03 Temat wiodący: Konstruktory i deskruktory. Konstruktory i Destruktory

Konstruktor kopiujacy

Projektowanie obiektowe. Roman Simiński Wzorce projektowe Wybrane wzorce strukturalne

Wprowadzenie do programowanie obiektowego w języku C++

Transkrypt:

Wprowadzenie do programowanie obiektowego w języku C++ Część czwarta Autor Roman Simiński Kontakt roman.siminski@us.edu.pl www.us.edu.pl/~siminski Niniejsze opracowanie zawiera skrót treści wykładu, lektura tych materiałów nie zastąpi uważnego w nim uczestnictwa. Opracowanie to jest chronione prawem autorskim. Wykorzystywanie jakiegokolwiek fragmentu w celach innych niż nauka własna jest nielegalne. Dystrybuowanie tego opracowania lub jakiejkolwiek jego części oraz wykorzystywanie zarobkowe bez zgody autora jest zabronione.

Koncepcja dziedziczenia wielobazowego o co chodzi? pozwala na tworzenie klas potomnych, dziedziczących z więcej niż jednej klasy bazowej. Mając np. dwie, zaimplementowane klasy, można zbudować nową klasę, dziedziczącą jednocześnie właściwości obu tych klas, co zwykle nie wymaga wprowadzania zmian w ich kodzie lub zmiany te są nieznaczne. Samochód Łódka Stół Okrąg Amfibia OkrągłyStół ListBox EditLine ComboBox Copyright Roman Simiński Strona : 2

Koncepcja dziedziczenia wielobazowego Za i przeciw dziedziczeniu wielobazowemu Tak pozwala programiście budować elastyczne i dobrze odwzorowujące rzeczywistość hierarchie klas. Nie zmusza programistę do większej uwagi, zwiększa złożoność języka oraz kompilatora. W wielu językach programowania zrezygnowano z dziedziczenia wielobazowego: jest np. w językach C++, Pyton, nie ma np. w językach Object Pascal, Javia, C#. Copyright Roman Simiński Strona : 3

syntaktyka Anatomia dziedziczenia wielobazowego class A int amember; class B int bmember; class C : public A, public B int cmember;... C obj; obj.amember = 0; obj.bmember = 1; obj.cmember = 2; Obiekt obj klasy C składa się z pól: amember, bmember, cmember, a ich kolejność jest taka, jak kolejność nazw klas w deklaracji klasy C. Copyright Roman Simiński Strona : 4

syntaktyka Aktywowanie konstruktorów Kolejność aktywowania konstruktorów dla obiektu klasy pochodnej wynika z kolejności występowania nazw klas bazowych w deklaracji tej klasy. Nie jest istotna kolejność ich umieszczenia na liście inicjalizacyjnej konstruktora klasy pochodnej. Specjalnie traktowane są wirtualne klasy bazowe ale o tym później. Kolejność aktywowania destruktorów jest odwrotna do kolejności stosowanej w przypadku konstruktorów. Copyright Roman Simiński Strona : 5

syntaktyka Aktywowanie konstruktorów class A A() : amember( 0 ) cout << "Konstruktor: A()" << endl; ~A() cout << "Destruktor: ~A()" << endl; int amember; class B B() : bmember( 0 ) cout << "Konstruktor: B()" << endl; ~B() cout << "Destruktor: ~B()" << endl; int bmember; Copyright Roman Simiński Strona : 6

syntaktyka Aktywowanie konstruktorów, cd.... class C : public A, public B C() : A(), B(), cmember( 0 ) cout << "Konstruktor: C()" << endl; ~C() cout << "Destruktor: ~C()" << endl; int cmember; int main() C obj; obj.amember = 0; obj.bmember = 1; obj.cmember = 2; return 0; Copyright Roman Simiński Strona : 7

Składowe o tej samej nazwie class A int member; void memberfunction() A +member +memberfunction() B +member +memberfunction() class B int member; void memberfunction() class C : public A, public B int cmember; void cmemberfunction();... C obj;... member member cmember C +cmember +cmemberfunction() obj : tylko pola obiektu Klasa A Klasa B Klasa C Copyright Roman Simiński Strona : 8

Składowe o tej samej nazwie, cd.... Odwołania jednoznaczne: obj.cmember = 10; obj.cmemberfunction(); Odwołanie niejednoznaczne: obj.member = 100; obj.memberfunction(); Błąd kompilacji (np. Dev-C): Request for member 'member' is ambiguous, candidates are: int B::member is int A::member Błąd kompilacji (np. Borland C++ Builder): Member is ambiguous: 'A::member' and 'B::member' Member is ambiguous: 'A::memberFunction' and 'B::memberFunction' Copyright Roman Simiński Strona : 9

Składowe o tej samej nazwie, wykorzystanie operatora zasięgu :: Odwołania jednoznaczne: obj.a::member = 100; obj.b::member = 200; cout << obj.a::member << endl; obj.a::memberfunction(); cout << obj.b::member << endl; obj.b::memberfunction(); Odwołania jednoznaczne via wskaźniki: C * ptr; ptr = new C; ptr->a::member = 100; ptr->b::member = 200; cout << ptr->a::member << endl; ptr->a::memberfunction(); cout << ptr->b::member << endl; ptr->b::memberfunction(); delete ptr; Copyright Roman Simiński Strona : 10

Składowe o tej samej nazwie, przykład klasa Amphibian class Vehicle Vehicle( int maxspeed = 0, int numofwheels = 0 ) : maxspeed( maxspeed ), numofwheels( numofwheels ) protected: int maxspeed; int numofwheels; class Boat Boat( int maxspeed = 0, int displacement = 0 ) : maxspeed( maxspeed ), displacement( displacement ) protected: int maxspeed; int displacement; Copyright Roman Simiński Strona : 11

Składowe o tej samej nazwie, przykład klasa Amphibian, cd.... class Amphibian : public Vehicle, public Boat Amphibian( int maxlandspeed = 0, int maxwaterspeed = 0, int numofwheels = 0, int displacement = 0 ) : Vehicle( maxlandspeed, numofwheels ), Boat( maxwaterspeed, displacement ) int getmaxlandspeed() const return Vehicle::maxSpeed; int getmaxwaterspeed() const return Boat::maxSpeed; int getnumofwheels() const return numofwheels; int getdisplacement() const return displacement;... Amphibian a( 120, 20, 4, 1500 ); cout << endl << "Maks. predk. na ladzie : " << a.getmaxlandspeed(); cout << endl << "Maks. predk. na wodzie : " << a.getmaxwaterspeed(); cout << endl << "Liczba kol : " << a.getnumofwheels(); cout << endl << "Wypornosc : " << a.getdisplacement(); Copyright Roman Simiński Strona : 12

Problemów ciąg dalszy Pewien potomek (klasa pochodna) może mieć rodziców (klasy bazowe) mających wspólnego przodka (wspólną klasę bazową). Powoduje to pewne komplikacje dla potomka. Środek Transportu Środek Transportu Control Control Samochód Łódka ListBox EditLine Amfibia ComboBox Bezpośrednia klasa bazowa klasy A klasa, z której klasa A dziedziczy. Pośrednia klasa bazowa klasy A klasa, z której dziedziczy bezpośrednia klasa bazowa klasy A. Copyright Roman Simiński Strona : 13

Dziedziczenie ze wspólną, pośrednią klasą bazową class A int member; void memberfunction() class B : public A int bmember; class C : public A int cmember; class D : public B, public C int dmember; Copyright Roman Simiński Strona : 14

Dziedziczenie ze wspólną, pośrednią klasą bazową Odwołania niejednoznaczne (błędy kompilacji): D obj; obj.member = 100; obj.memberfunction(); A +member +memberfunction() A +member +memberfunction() member bmember Klasa A Klasa B +bmember B +cmember C member cmember Klasa A Klasa C Klasa D +dmember D dmember obj : tylko pola obiektu W przypadku dziedziczenia wielobazowego po klasach mających wspólna klasę bazową, klasa pochodna posiada w sobie wielokrotnie składowe występujące we wspólnej klasie bazowej. Ma to szczególne znaczenie w przypadku pól. Copyright Roman Simiński Strona : 15

Usuwanie niejednoznaczności ponownie operator zakresu D obj; obj.b::member = 100; obj.c::memberfunction(); D * ptr = new D; ptr->b::member = 100; ptr->c::memberfunction();... W tym przypadku wystąpienie kopii pól jest semantycznie niepoprawne. Powoduje to również stratę pamięci. Problem z wykorzystaniem wskaźników do klasy bazowej A * ptr1= new D; A * ptr2= new B; A * ptr3= new C; A * ptr1= (C *)new D; // Błąd // OK // OK // OK, wymagana konwersja Copyright Roman Simiński Strona : 16

Dziedziczenie w trybie wirtualnym klasy bazowe virtual Dziedziczenie w trybie wirtualnym ma na celu wyeliminowanie niejednoznaczności przy wielokrotnym dziedziczeniu ze wspólnych klas bazowych. Zadeklarowanie klasy bazowej jako wirtualnej informuje kompilator, że ma umieścić w klasach pochodnych tylko jedno wystąpienie składowych wirtualnej klasy bazowej. Środek Transportu Control Samochód Łódka ListBox EditLine Amfibia ComboBox Copyright Roman Simiński Strona : 17

Anatomia dziedziczenia w trybie wirtualnym class A int member; void memberfunction() class B : virtual public A int bmember; class C : virtual public A int cmember; class D : public B, public C int dmember; Kolejność występowania słów kluczowych public i virtual jest dowolna. Copyright Roman Simiński Strona : 18

Anatomia dziedziczenia w trybie wirtualnym Odwołania jednoznaczne D obj; obj.member = 100; obj.memberfunction();... obj.b::member = 100; obj.c::memberfunction();... // Teraz tylko jedno wystąpienie tego pola // Teraz tylko jedno wystąpienie tej funkcji // Tak można było poprzednio i teraz również // j.w. Dziedziczenie wirtualne aktywowanie konstruktorów Konstruktory klas wirtualnych są aktywowane przed konstruktorami klas niewirtualnych. Gdy klas wirtualnych jest więcej, kolejność aktywacji odpowiada kolejności deklaracji. Jeżeli klasa wirtualna dziedziczy z klasy niewirtualnej, konstruktor tej ostatniej będzie aktywowany wcześniej. Konstruktory pozostałych niewirtualnych klas bazowych są aktywowane zgodnie z kolejnością deklaracji. Aktywowane są konstruktory obiektów składowych. Aktywowany jest konstruktor klasy pochodnej. Copyright Roman Simiński Strona : 19

Dziedziczenie wirtualne aktywowanie konstruktorów, cd.... Jeżeli w hierarchii klas występują jednocześnie wirtualne i niewirtualne wystąpienia tej samej klasy, konstruktor tej klasy jest wywoływany raz dla wszystkich wystąpień wirtualnych oraz raz dla każdego niewirtualnego wystąpienia klasy class A class B class C: public B, virtual public A class D: public B, virtual public A class E: public C, virtual public D class A class B: virtual public A class C: virtual public A class D: public A class E: public B, public C, public D B A B A A C D B C D E E A(); B(); D(); B(); C(); E(); A(); B(); C(); A(); D(); E(); Copyright Roman Simiński Strona : 20

Dziedziczenie wirtualne aktywowanie konstruktorów, cd.... Wprowadzamy konstruktory ogólne: class A A() : a( 0 ) cout << "Default A: a = 0" << endl; A( int a ) : a( a ) cout << "General A: a = " << a << endl; int a; class B: virtual public A B() : A() cout << "Default B" << endl; B( int a, int b ) : A( a ), b( b ) cout << "General B: b = " << b << endl; int b; Copyright Roman Simiński Strona : 21

Dziedziczenie wirtualne aktywowanie konstruktorów, cd.... class C: virtual public A C() : A() cout << "Default C"; C( int a, int c ) : A( a ), c( c ) cout << "General C: c = " << c << endl; int c; class D: public B, public C D() : B(), C() cout << "Default D"; D( int a, int b, int c, int d ) : B( a, b ), C( a, c ), d( d ) cout << "General D: d = " << d << endl; int d;... D obj( 1, 2, 3, 4 ); cout << "a: " << obj.a << endl; cout << "b: " << obj.b << endl; cout << "c: " << obj.c << endl; cout << "d: " << obj.d << endl; Copyright Roman Simiński Strona : 22

Niby wszystko w porządku ale :-/ Dlaczego pole a wirtualnej klasy bazowej A ma wartość 0? Przecież: D obj( 1, 2, 3, 4 ); Co się dzieje? Przecież: Dlaczego pole a ma wartość 0? Jak nadać mu właściwą wartość? Normalnie programista nie musi się przejmować inicjalizacją składowych odziedziczonych po pośrednich klasach bazowych (czyli A dla klasy D). Zajmują się tym konstruktory bezpośrednich i występujących wcześniej w hierarchii pośrednich klas bazowych (czyli B i C dla klasy D). Istnieją jednak dwie drogi realizacji inicjalizacji poprzez klasę B lub poprzez klasę C. Ponownie mamy niejednoznaczność, która klasa B czy C jest odpowiedzialna za inicjalizację pola a? Copyright Roman Simiński Strona : 23

Wirtualne klasy bazowe wymagają specjalnej inicjalizacji Z powodu niejednoznaczności, w przypadku dziedziczenia wielobazowego z klasą wirtualną: Klasa pochodna musi zainicjalizować jawnie składowe wirtualnej klasy bazowej. class D: public B, public C... D( int a, int b, int c, int d ) : A( a ), B( a, b ), C( a, c ), d( d ) cout << "General D: d = " << d << endl; Konstruktor klasy pochodnej jawnie inicjalizuje składowe wirtualnej klasy bazowej, aktywując jej konstruktor na liście inicjalizującej. Copyright Roman Simiński Strona : 24

Wirtualne klasy bazowe wymagają specjalnej inicjalizacji A co z aktywacją konstruktorów klasy A z listy inicjalizacyjnej klas B i C? Konstruktory te są: Niezbędne, gdy są stworzone samodzielne obiekty klas B i C, wtedy działają normalnie. Jeżeli działają dla obiektu klasy potomnej obiektu klasy D ignorowana jest inicjalizacja składowych wirtualnej klasy bazowej A. W omawianym przypadku kompilator zajmuje się modyfikowaniem działania konstruktorów. Obowiązkiem programisty jest: Wiedzieć, że w budowanej przez niego hierarchii klas występuje dziedziczenie wielobazowe z wirtualnymi klasami bazowymi. Inicjalizować w klasie pochodnej składowe odziedziczone, nawet pośrednio, po wirtualnej klasie bazowej. Copyright Roman Simiński Strona : 25

Na zakończenie: Problemów z dziedziczeniem wielobazowym jest wiele. Dlatego w wielu językach obiektowych zrezygnowano z tego rodzaju dziedziczenia, wykorzystując tylko dziedziczenie jednobazowe. Copyright Roman Simiński Strona : 26