Podstawy i języki programowania



Podobne dokumenty
Wprowadzenie do programowanie obiektowego w języku C++

Wprowadzenie do programowanie obiektowego w języku C++

Wprowadzenie do programowanie obiektowego w języku C++

Programowanie w języku C++

Podstawy programowania skrót z wykładów:

class Student Deklaracja klasy Osoba: Deklaracja klasy Student:

1. Pierwszy program. Kompilator ignoruje komentarze; zadaniem komentarza jest bowiem wyjaśnienie programu człowiekowi.

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

Podstawy Programowania Obiektowego

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

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej.

Wstęp do programowania. Wykład 1

Język C++ Różnice między C a C++

Podstawy programowania w języku C++

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta Strona 1 z 26. Powrót. Full Screen. Zamknij.

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

TEMAT : KLASY DZIEDZICZENIE

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Wykład 8: klasy cz. 4

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

Podstawy programowania w języku C++

Mechanizm dziedziczenia

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

Podstawy programowania. Wykład: 5. Instrukcje sterujące c.d. Stałe, Typy zmiennych c.d. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

Wprowadzenie do programowania w języku C

Podstawy Informatyki. Inżynieria Ciepła, I rok. Wykład 10 Kurs C++

W2 Wprowadzenie do klas C++ Klasa najważniejsze pojęcie C++. To jest mechanizm do tworzenia obiektów. Deklaracje klasy :

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

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 15 kwietnia K.Grzelak (Wykład 8) Programowanie w C++ 1 / 33

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

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

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

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

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Materiały do zajęć VII

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++

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

Wstęp do programowania

Wykład 5: Klasy cz. 3

Laboratorium nr 12. Temat: Struktury, klasy. Zakres laboratorium:

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

Język C++ zajęcia nr 2

Programowanie w języku C++

Podstawy programowania w języku C++

Programowanie w C++ Wykład 9. Katarzyna Grzelak. 14 maja K.Grzelak (Wykład 9) Programowanie w C++ 1 / 30

Podstawowe elementy proceduralne w C++ Program i wyjście. Zmienne i arytmetyka. Wskaźniki i tablice. Testy i pętle. Funkcje.

Wykład VII. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

Wstęp do informatyki- wykład 11 Funkcje

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

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

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

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

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static),

Programowanie obiektowe w języku C++ dr inż. Jarosław Forenc

Szablony funkcji i szablony klas

Wykład II Tablice (wstęp) Przykłady algorytmów Wstęp do języka C/C++

Język ludzki kod maszynowy

Wstęp do programowania obiektowego. Wykład 2

Wstęp do informatyki- wykład 9 Funkcje

Programowanie obiektowe - 1.

Języki i paradygmaty programowania

wykład IV uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C, a C++. wykład IV dr Jarosław Mederski Spis Język C++ - wstęp

1 Definiowanie prostych klas

Wykład 4: Klasy i Metody

Wprowadzenie do obiektowości

Do czego służą klasy?

PARADYGMATY PROGRAMOWANIA Wykład 4

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.

referencje Wykład 2. Programowanie (język C++) Referencje (1) int Num = 50; zdefiniowano zmienną Num (typu int) nadając jej wartość początkową 50.

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

Podstawy algorytmiki i programowania - wykład 4 C-struktury

Programowanie obiektowe w języku C++

Podstawy programowania w języku C++

Programowanie, część I

Programowanie obiektowe

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Funkcje. Spotkanie 5. Tworzenie i używanie funkcji. Przekazywanie argumentów do funkcji. Domyślne wartości argumentów

Zad. 5: Układ równań liniowych liczb zespolonych

Szablony klas, zastosowanie szablonów w programach

Przekazywanie argumentów wskaźniki

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

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

Wykład 9: Polimorfizm i klasy wirtualne

Podstawy programowania w języku C++

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

Języki programowania. Przetwarzanie tablic znaków. Część druga. Autorzy Tomasz Xięski Roman Simiński

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

Podstawy programowania w C++

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Laboratorium 1. Wprowadzenie, środowisko programistyczne, pierwsze programy

Podstawy programowania

wykład V uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C++ klasy i obiekty wykład V dr Jarosław Mederski Spis Język C++ - klasy

Języki programowania. Przetwarzanie plików amorficznych Konwencja języka C. Część siódma. Autorzy Tomasz Xięski Roman Simiński

Jeśli chcesz łatwo i szybko opanować podstawy C++, sięgnij po tę książkę.

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

Wstęp do programowania

2 Przygotował: mgr inż. Maciej Lasota

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

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

Transkrypt:

Materiały dydaktyczne Podstawy i języki programowania Część trzecia Wprowadzenie do programowania w języku C++ Temat opracowania Łagodny start Autor Roman Simiński siminski@us.edu.pl Niniejsze opracowanie zawiera skrót treści wykładu, lektura tych materiałów nie zastąpi uważnego uczestnictwa w wykładzie. 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.

Bjarne Stroustrup twórca języka C++ Wprowadzenie do programowania w C++ historia języka Bjarne Stroustrup twórca języka C++, autor książek: Język programowania C++ (ang. The C++ Programing Language), trzy edycje + edycja specjalna; Projektowanie i ewolucja C++ (ang. The Design and Evolution of C++). Urodzony w 1950 w Aarhus (Dania), skończył studia w swym rodzinnym mieście, doktorat obronił na Uniwersytecie w Cambridge. Od 1979 roku związany z centrum badawczym firmy Bell. Aktualnie pracuje jako profesor w Texas A&M University, utrzymując jednocześnie swoje związki z firmą AT&T jako członek zespołu badawczego laboratorium tej firmy. Jak powstał język C++? 1979 Bjarnie Sroustrup, pracujący w Centrum Badań Komputerowych Laboratorium firmy Bell (ang. Computing Science Research Center of Bell Labs) prowadzi badania symulacyjne związane z sieciami komputerowymi. Język Simula, idealny do symulacji pod względem funkcjonalnym jest za mało efektywny. Stroustrup potrzebuje nowego, obiektowego języka programowania łączącego funkcjonalność języka Simula z efektywnością języka C. 1980 Bjarne Stroustrup projektuje język programowania łączący w sobie cechy języków Simuai i C. Język zostaje nazwany C z klasami (ang. C with Classes). Wersja ta nie zawiera jeszcze znanych aktualnie z C++ rozbudowanych mechanizmów obiektowych. 1983 Rick Mascitti proponuje nazwę C++ dla nowego języka. Nazwa sugeruje ewolucyjna naturę C++ w stosunku do języka C. Nowy język nie został nazwany D, ponieważ stanowi on rozszerzenie C a nie próbę stworzenia nowego jakościowo języka programowania. Copyright Roman Simiński 2

1985 Wprowadzenie do programowania w C++ historia języka Język C++ zostaje zaprezentowany publicznie z możliwością wykorzystania poza Laboratorium Bell. Powstaje pierwszy komercyjny kompilator C++ : cfront. Jest to tak na prawdę translator, tłumaczący kod w języku C++ na kod w języku C, kompilowany następnie zwykłym kompilatorem języka C. 1989 Michael Tiemann (firma Cygnus Support) implementuje pierwszy prawdziwy kompilator C++, zwany G++. Publikacja pierwszej specyfikacji C++ w postaci książki The Annoutated C++ Reference Manual autorstwa Stroustrupa i Ellisa, znanej jako ARM. Rozpoczyna się proces standaryzacji języka. Po co standard? Oficjalny standard określa precyzyjnie interpretację każdej konstrukcji. Bez tego twórcy kompilatorów pozwalają sobie na własne, różne interpretacje tych samych konstrukcji językowych. Brak standardu ogranicza możliwość pisania w pełni przenośnego oprogramowania. Kto pracuje nad standardem? ANSI American National Standard Institute, ISO International Standard Organization. Konstytuuje się komitet ANSI (X3J16) do sformułowania zarysu standardu C++. 1995 Komitet ANSI publikuje pierwszą wersję zarysu standardu C++. Rozpoczyna się uciążliwy proces rewizji standardu wymaga on wielu poprawek. 1996 Grudzień, zostaje opublikowany szkic standardu ANSI C++. 1997 Grudzień, oficjalna premiera pełnej wersji standardu ANSI C++. Copyright Roman Simiński 3

1998 Wprowadzenie do programowania w C++ historia języka Czerwiec, oficjalna aprobata dla opublikowanego standardu. Standard zostaje również zaaprobowany przez ISO. Zamrożenie prac na pięć lat okres na adaptację producentów kompilatorów i poprawę błędów. W międzyczasie... Powstaje nowy standard C C99, ANSI/ISO C++ jest zgodny z C89. Powstaje i rozwija się język Java obejmujący w standardzie możliwość programowania grafiki, wielowątkowego i sieciowego. Powstaje i rozwija się promowany przez Microsoft język C#. Ciekawostka... Skoro jest C++ to może jest C--? Jest! Autorzy projektu proponują aby kompilatory języków wysokiego poziomu tłumaczyły kod źródłowy na kod w języku C--, pozostawiając kompilatorowi C-- generowanie optymalnego kodu maszynowego. C-- jest zatem pewnego rodzaju uniwersalnym językiem assemblera, niezależnym od platformy sprzętowej. Literatura Język C++ S.B. Lippman, J. Lajoie, Podstawy języka C++,WNT, 2003. P.J. Plauger, Biblioteka standardowa C++, WNT, 1997. B. Stroustrup, Język C++, WNT, 2002 Liberty J. C++ dla każdego, Helion, 2002. Bruce Eckel, Thinking in C++ 2nd Edition, dostępne via Internet: http://www.mindview.net/books/ticpp/thinkingincpp2e.html Obiektowa analiza, projektowanie, programowanie P. Coad, E. Yourdon, Analiza obiektowa, Oficyna Wydawnicza Read Me, 1994. P. Coad, E. Yourdon, Projektowanie obiektowe, Oficyna Wydawnicza Read Me, 1994. P. Coad, J. Nicola, Programowanie obiektowe, Oficyna Wydawnicza Read Me, 1993. Copyright Roman Simiński 4

Od C do C++ mały krok do przodu Program obliczający średnie spalanie paliwa #include <iostream> using namespace std; int main() float dystans, paliwo; Wprowadzenie do programowania w C++ od C do C++ cout << "Obliczam ile Twoj pojazd spala paliwa na 100 km" << endl; cout << "Potrzebuje dystans przejechanych kilometrow"; cout << " i zuzycie paliwa w litrach" << endl; cout << "Dystans : " << flush; cin >> dystans; cout << "Paliwo : " << flush; cin >> paliwo; if( dystans == 0 ) cout << "Nie policze spalania dla zerowego dystansu" << endl; else cout << "Spalanie " << ( paliwo * 100 ) / dystans << " l na 100 km" << endl; return 0; Strumienie w C++ krótkie wprowadzenie Biblioteka standardowa oferuje predefiniowane obiekty obsługi strumieni programu: cin strumień reprezentujący standardowe wejście programu, odpowiada strumieniowi stdin z C. Strumień cin odczytuje dane i zapisuje je do odpowiednich zmiennych. cout strumień reprezentujący standardowe wyjście programu. Odpowiada strumieniowi stdout z C. cerr niebuforowany strumień wyjściowy błędów. Odpowiada strumieniowi stderr z C. clog buforowany strumień wyjściowy błędów. Odpowiada strumieniowi stderr z C. Aby skorzystać z strumieni cin, cout, cerr należy włączyć odpowiedni plik nagłówkowy Starsze kompilatory przed standaryzacją odwołań do plików nagłówkowych #include <iostream.h> Aktualny standard #include <iostream> using namespace std; Copyright Roman Simiński 5

Wprowadzenie do programowania w C++ od C do C++ Wykorzystanie strumienia cout podstawowe informacje Wyprowadzanie danych odbywa się z wykorzystaniem operatora <<, zwanego wstawiaczem (ang. inserter). Dane są wyprowadzane zgodnie z ich typem, istnieje możliwość formatowania postaci wyjściowej. #include <iostream> using namespace std; Dwa style wykorzystania strumienia cout #include <iostream> using namespace std; int main() int i = 10; float f = 5.5; char c = A ; char s[] = "Test cout"; cout << "i = "; cout << i; cout << \n ; cout << "f = "; cout << f; cout << \n ; cout << "c = "; cout << c; cout << \n ; cout << "s = "; cout << s; cout << \n ; int main() int i = 10; float f = 5.5; char c = A ; char s[] = "Test cout"; cout << "i = " << i << endl; cout << "f = " << f << endl; cout << "c = " << c << endl; cout << "s = " << s << endl; return 0; return 0; Przykład prostego formatowania #include <iostream> using namespace std; int main() int i = 12345; int j = 255; cout << ; cout.width( 10 ); cout << i << << endl; cout << ; cout.setf(ios::left); cout.width( 10 ); cout << i << << endl; cout << "Dziesietnie : " << dec << j << endl; cout << "Osemkowo : " << oct << j << endl; cout << "Szesnastkowo : " << hex << j << endl; return 0; Manipulatory flush i endl powodują opróżnienie bufora strumienia cout, endl wstawia znak nowej linii przed opróżnieniem bufora. Copyright Roman Simiński 6

Wprowadzenie do programowania w C++ od C do C++ Wykorzystanie strumienia cin podstawowe informacje Globalny obiekt cin umożliwia wczytywanie danych z wykorzystaniem operatora >> zwanego wydobywaczem (ang. extractor), który przeprowadza konieczne konwersje w trakcie pobierania danych. #include <iostream> using namespace std; int main() int i; float f; char s[ 80 ]; cout << "Wprowadz lb. calkowita cin >> i; : " << flush; cout << "Wprowadz lb. rzeczywista : " << flush; cin >> f; cout << "Wprowadz napis cin >> s; cout << "i = " << i << endl; cout << "f = " << f << endl; cout << "s = " << s << endl; return 0; : " << flush; Operator >> pomija białe znaki w strumieniu wejściowym char c; cin >> c; // Odczytuje z wejścia następny znak nie będący znakiem białym cin.get( c ); // Odczytuje z wejścia następny znak, być może to biały znak const int size; char s[ size ]; cin >> s; cin.getline( s, size ); Zastosowanie const int size; char c; char s[ size ]; // Odczytuje słowo do pierwszego białego znaku // Odczytuje maks. SIZE znak w do znaku nowej linii cout << "Wprowadz znak : "; c = cin.get(); cin.ignore(); // Pominięcie oczekującego Enter a cout << "Wprowadzono : " << c << endl; cout << "Wprowadz napis : "; cin.getline( s, size ); cout << "Wprowadzono : " << s << endl; Copyright Roman Simiński 7

Wprowadzenie do programowania w C++ od C do C++ Gra w Za dużo, za mało wersja w wykorzystaniem strumieni #include <iostream> #include <cstdlib> #include <ctime> using namespace std; int main() int wczytana, wylosowana; cout << endl << "Witaj w grze w \"Za duzo, za malo\""; cout << endl << "Odgadnij wylosowana liczbe (1.. 100)" << endl; srand( 1000 ); wylosowana = rand() % 100 + 1; do cout << > << flush; cin >> wczytana; if( wczytana > wylosowana ) cout << "Za duzo" << endl; else if( wczytana < wylosowana ) cout << "Za malo" << endl; else cout << "Brawo, to ta liczba!" << endl; while( wylosowana!= wczytana ); return 0; W programach w C++ można korzystać z bibliotek języka C Kompilatory przed standaryzacją odwołań do plików nagłówkowych #include <stdlib.h> #include <time.h> #include <ctype.h> Aktualny standard #include <cstdlib> #include <ctime> #include <cctype> using namespace std; Lepsza inicjalizacja generatora liczb pseudolosowych srand( ( unsigned )time( NULL ) ); Lepsze ograniczenie zakresu losowanych liczb wylosowana = int( 100.0 * rand()/( RAND_MAX + 1.0 ) ) + 1; Program powyższy napisany został w C++ z wykorzystaniem obiektowej biblioteki we/wy. Czy ten program jest obiektowy? Copyright Roman Simiński 8

Wprowadzenie do programowania w C++ model obiektowy w pigułce Obiektowe podejście do projektowania systemów informatycznych OOA, OOD, OOP Analiza obiektowa, OOA Object Oriented Analysis Celem analizy obiektowej jest stworzenie modelu, w którym każdy element świata rzeczywistego odwzorowany jest odpowiednim obiektem (lub ich grupą), należącym do określonej klasy. Interakcja pomiędzy obiektami jest odbiciem procesów zachodzących w rzeczywistości. Projektowanie obiektowe, OOD Object Oriented Design Celem projektowania obiektowego jest opisanie struktury projektowanego systemu w kategoriach obiektów i klas do których należą, stosując odpowiednie notacje, odwzorowujące logiczne i fizyczne właściwości obiektów oraz opisujące ich właściwości statyczne i dynamiczne. Programowanie obiektowe, OOP Object Oriented Programming Programowanie obiektowe zakłada organizację programu jako zbioru współpracujących ze sobą obiektów, będących reprezentantami pewnych klas. Klasy te należą do hierarchii klas, opisanej zunifikowanymi sposobami odwzorowania relacji występujących pomiędzy klasami. Wynika z tego, że programowanie obiektowe: bazuje na obiektach a nie algorytmach podstawowymi blokami logicznymi programu są zatem obiekty a nie podprogramy; każdy obiekt jest reprezentantem pewnej klasy, klasa określa właściwości i możliwości każdego obiektu; klasy są ze sobą powiązane tworząc pewną hierarchię, podstawą do jej budowania relacje pomiędzy klasami, główną jest dziedziczenie właściwości klas. OOA OOD OOP Model piłeczki baseball owej Copyright Roman Simiński 9

Wprowadzenie do programowania w C++ model obiektowy w pigułce Z punktu widzenia analizy i projektowania obiektowego Obiekt jest reprezentantem pewnej rzeczy lub koncepcji ze świata rzeczywistego. Klasa to opis obiektu (lub obiektów) o jednolitych właściwościach i możliwościach. Z punktu widzenia programowania obiektowego Obiekt posiada trzy cechy: Tożsamość (ang. identity), pozwala na odróżnienie danego obiektu od każdego innego. Programista przypisuje obiektowi unikatową nazwę lub włącza go do identyfikowalnej kolekcji obiektów lub odwołuje się do obiektu posługując się jego adresem w pamięci. Stan (ang. state), opisuje to co obiekt w danym momencie powinien wiedzieć aby sprawnie działać. Stan obiektu w danym momencie opisany jest zestawem atrybutów i ich wartości. Atrybuty są nazwami wewnętrznych danych obiektu, opisujących jego stan. Atrybuty zwane są polami (ang. fields) lub składowymi danych (ang. data members). Wartości atrybutów mogą się zmieniać w czasie wykonania programu. Zdolność do działania (ang. behavior) opisuje operacje, które obiekt może wykonać. Operacje są realizowane poprzez wykonanie metod (ang. methods) zwanych w C++ funkcjami składowymi (ang. member functions). Metody są jak procedury lub funkcje w programowaniu proceduralnym mogą otrzymywać parametry, mogą zwracać wartości. Metody są jednak częścią obiektu i mogą być aktywowane wtedy, gdy obiekt zostanie o to poproszony. Wykonanie metod zwykle zmienia stan obiektu a więc wartości jego pól. Copyright Roman Simiński 10

Wprowadzenie do programowania w C++ pierwsza klasa, pierwszy obiekt Definiujemy pierwszą klasę i pierwszy obiekt Definiujemy klasę opisującą kwadrat Square #include <iostream> using namespace std; class Square public : void setside( float side ); float getside(); float area(); private: float side; ; Tworzymy obiekt mygarden i każemy mu działać: int main() Square mygarden; mygarden.setside( 100 ); cout << endl << "Powierzchnia mojego ogrodu : " << mygarden.area(); return 0; Interakcja z obiektem polega na przesyłaniu do niego komunikatów: Przes³anie komunikatu obiekt : mygarden klasy : Square mygarden.setside( 100 ) Odbiorca komunikatu Nazwa komunikatu Parametr komunikatu setside getside area 100 side side * side < Obiekt odpowiada na komunikaty aktywując odpowiednie metody. Definiujemy metody odpowiedzi na komunikaty: void Square::setSide( float side ) Square::side = side; float Square::getSide() return side; float Square::area() return side * side; // Alternatywna wersja setside void Square::setSide( float newside ) side = newside; Metody poza ciałem klasy definiujemy z wykorzystaniem operatora zakresu ::. Zapis Square:: oznacza, że występujący po nim element należy do klasy Square. Copyright Roman Simiński 11

Wprowadzenie do programowania w C++ pierwsza klasa, pierwszy obiekt Kontrola dostępu do pól i metod Co oznaczają słowa kluczowe public i private? mygarden.side = 100; cout << mygarden.side Dwie podstawowe sekcje: // Błąd, side jest prywatną własnościa obiektu mygarden // Błąd, side jest prywatną własnościa obiektu mygarden private elementy zadeklarowane w tej sekcji mogą być wykorzystywane wyłącznie przez metody danej klasy. Elementami tymi mogą być zarówno pola i metody. Mówi się o nich, że są prywatne. public elementy zadeklarowane w tej sekcji są dostępne również dla innych elementów programu. Mówi się o nich, że są publiczne lub stanowią interfejs klasy. Część publiczna klasy określa jakie komunikaty można przesyłać do obiektu, inaczej mówiąc, jakie może on wykonywać usługi. Dwie metody kolejności zapisu sekcji public i private class C public: // Część publiczna klasy void interfacemethod(); private: // Część prywatna klasy void privatemethod(); int internaldata; ; class C private: // Część prywatna klasy void privatemethod(); int internaldata; public: // Część publiczna klasy void interfacemethod(); Czy można deklarować pola w części publicznej można, jednak zaleca się ukrywanie danych w części prywatnej i dostęp poprzez metody. < Stosowanie publicznych pól nie jest dobra praktyką. Jak dostać się do pól prywatnych? mygarden.setside( 100 ); cout << mygarden.getside() // OK, dostęp za pomocą akcesora // OK, dostęp za pomocą modyfikatora Metody publiczne klasy można nieformalnie podzielić na; akcesory metody umożliwiające pobieranie wartości pól, akcesorem jest np. metoda getside. modyfikatory metody dokonujące modyfikacji wartości pól, modyfikatorem jest np. metoda setside. realizatory metody realizujące właściwe dla danej klasy usługi, realizatorem jest np. metoda area. Copyright Roman Simiński 12

Wprowadzenie do programowania w C++ pierwsza klasa, pierwszy obiekt Jakimi wartościami obiekt jest inicjowany? Co się stanie gdy nie ustalimy rozmiaru boku obiektu klasy Square? Square mygarden; // Niezainicjowany obiekt const cout << endl << "Powierzchnia mojego ogrodu : " << mygarden.area(); Jak ustalić rozmiar boku dla obiektu const? const Square doghouse; // Niezainicjowany obiekt const doghouse.setside( 1.2 ); // Błąd pr ba modyfikacji obiektu const cout << endl << "Powierzchnia budy mojego psa : " << doghouse.area(); Wprowadzamy konstruktor domyślny klasy Square class Square public : Square(); void setside( float side ); float getside() const; float area() const; private: float side; ; Square::Square() : side( 0 ) Metody ze specyfikacją const nie mogą modyfikować pól obiektu, mogą zatem być wywoływane dla obiektów const. // Alternatywna wersja konstruktora Square::Square() side = 0; Konstruktor jest specjalną funkcja aktywowaną przez kompilator automatycznie w momencie gdy obiekt jest tworzony. Dzieje się tak zanim programista będzie mógł dorwać obiekt. < Konstruktor nie ma typu rezultatu, nosi taką nazwę jak nazwa klasy i zwykle nie wywołuje się go jawnie w kodzie programu. Nazwa pola Wyra enie inicjalizuj¹ce Square::Square() : side( 0 ) Lista inicjalizuj¹ca konstruktora Square() to konstruktor bezparametrowy zwany konstruktorem domyślnym (ang. default constructor). Square a, b, c; // Aktywacja: a.square(), b.square(), c.square() Square squares[ 10 ]; // Aktywacja Square() dla ka żdego z 10-ciu elem. tablicy Copyright Roman Simiński 13

Problem Wprowadzenie do programowania w C++ pierwsza klasa, pierwszy obiekt const Square doghouse; // Zainicjowany obiekt const cout << endl << "Powierzchnia budy mojego psa : " << doghouse.area(); Zawsze zerowy bok zawsze zerowe pole? Jak zainicjować obiekt inną wartością niż domyślna? Wprowadzamy konstruktor parametrowy klasy Square class Square public : Square(); Square( float side ); void setside( float side ); float getside() const; float area() const; private: float side; ; Square::Square( float side ) : side( side ) Square mygarden( 100 ); const Square doghouse( 1 ); cout << endl << "Powierzchnia mojego ogrodu : " << mygarden.area(); cout << endl << "Powierzchnia budy mojego psa : " << doghouse.area(); Square( float side ) to konstruktor parametrowy zwany konstruktorem ogólnym (ang. general constructor). W języku C++ można przeciążać funkcje i operatory: Square() Square( float side ) Jedna nazwa, dwie różne funkcje różniące się parametrami int add( int a, int b ) return a + b; double add( double a, double b ) return a + b; // Alternatywne wersje konstruktora Square::Square( float side ) Square::side = side; Square::Square( float startside ) side = startside; cout << endl << "Dodawanie int :" << add( 1, 1 ) cout << endl << "Dodawanie double :" << add( 1.0, 1.0 ); Copyright Roman Simiński 14

Wprowadzenie do programowania w C++ pierwsza klasa, pierwszy obiekt Dla typów wbudowanych (standardowych) można tak: int j = 1; int i = j; Czy można tak samo dla obiektów? Square mygarden( 100 ); Square mywifegarden = mygarden; Ano można, ale w takiej sytuacji najlepiej zdefiniować nowy konstruktor class Square public : Square(); Square( float side ); Square( Square & othersquare ); void setside( float side ); float getside() const; float area() const; private: float side; ; Square::Square( Square & othersquare ) : side( othersquare.side ) Square( Square & othersquare ) to konstruktor kopiujący (ang. copy constructor), odpowiedzialny za skopiowanie zawartości jednego obiekty do drugiego oba tej samej klasy na etapie inicjalizacji. Można teraz tak: Square mygarden( 100 ); Square mywifegarden = mygarden; // lub mywifegarden( mygarden ); cout << endl << "Powierzchnia mojego ogrodu : " << mygarden.area(); cout << endl << "Powierzchnia ogrodu zony Ale nie można: Square mygarden( 100 ); Square mywifegarden; Operator & oznacza w C++ referencję, umieszczony w deklaracji parametru odpowiada za przekazanie parametru przez zmienną. : " << mywifegarden.area(); mywifegarden = mywifegarden; // Tutaj nie zostaje wywo łany konstruktor kopiujący Nie można: const Square doghouse( 1 ); Square cathouse = doghouse; // Błąd, niejawna referencja do obiektu const Rozwiązanie problemu z obiektem const: Square::Square( const Square & othersquare ) : side( othersquare.side ) Copyright Roman Simiński 15

Definicja klasy Rectangle class Rectangle public : ; Wprowadzenie do programowania w C++ konstruktory pod lupą Rectangle(); Rectangle( float width, float height ); Rectangle( const Rectangle & otherrectangle ); void setwidth( float width ) Rectangle::width = width; void setheight( float height ) Rectangle::height = height; float getwidth() const return width; float getheight() const return height; float area() const; private: float width, height; Rectangle::Rectangle() : width( 0 ), height( 0 ) Rectangle::Rectangle( float width, float height ) : width( width ), height( height ) Rectangle::Rectangle( const Rectangle & otherrectangle ) : width( otherrectangle.width ), height( otherrectangle.height ) float Rectangle::area() const return width * height; Czy można: Square s( 100 ); Rectangle r( s ); // Deklaracja zainicjowanego kwadratu s // Deklaracja prostokąta r z inicjalizacją kwadratem s Copyright Roman Simiński 16

Wprowadzenie do programowania w C++ konstruktory pod lupą Wprowadzamy konstruktor rzutujący klasy Rectangle Rectangle( const Square & square ) to konstruktor rzutujący (ang. cast, conversion constructor), odpowiedzialny za skopiowanie zawartości jednego obiekty do drugiego obiekty są różnych klas na etapie inicjalizacji. class Rectangle Rectangle( const Square & square ); ; Rectangle::Rectangle( const Square & square ) : width( square.getside() ), height( square.getside() ) Informacja dodatkowa parametry domyślne Parametr domyślny to wartość określona na etapie deklaracji funkcji, która zostanie automatycznie wstawiona jeżeli dana funkcja zostanie wywołana z pominięciem parametru. Dotyczy funkcji składowych jak i niezwiązanych z klasami. void fun( int i, float f = 0, char c = A ); fun( 10 ); // i == 10, f == 0, c == A fun( 20, 3.15 ); // i == 20, f == 3.15, c == A fun( 30, 22.1, Z ); // i == 30, f == 22.1, c == Z Podsumowanie informacji o konstruktorach Konstruktor domyślny default constructor A() A( arg1 = wart1, arg2 = wart2,... ) Jest bezparametrowy, lub posiada wszystkie parametry będące parametrami domyślnymi. Inicjowania obiektów, deklarowanych (bądź tworzonych) bez parametrów A obj; Konstruktor kopiujący copy constructor A( A & obj ) A( A & obj, arg1 = wart1,... ) A( const A & obj ) A( const A & obj, arg1 = wart1,... ) Jest to konstruktor, który posiada jeden parametr będący referencją obiektu tej samej klasy. Innych argumentów może nie być lub powinny być one argumentami domyślnymi. Konstruktor kopiujący jest używany wszędzie tam, gdzie deklarowany obiekt jest inicjowany wartością innego obiektu tej samej klasy. A obj1; A obj2 = obj1; A obj3( obj2 ); Copyright Roman Simiński 17

Wprowadzenie do programowania w C++ konstruktory pod lupą Konstruktor rzutuj¹cy conversion (cast) constructor A( B & obj ) A( B & obj, arg1 = wart1,... ) A( const B & obj ) A( const B & obj, arg1 = wart1,... ) Posiada jeden parametr będący referencją obiektu innej klasy. Innych argumentów może nie być lub powinny być one argumentami domyślnymi. Jest stosowany wszędzie tam, gdzie należy zainicjować obiekt pewnej klasy wartością obiektu innej klasy. B BObj; A AObj = BObj; < Programista może dzięki konstruktorowi rzutującemu określić w jaki sposób informacje zapisane w obiekcie klasy B mają zostać odwzorowane w obiekcie klasy A. Konstruktor ogólny (główny) general constructor A( arg1, arg2,... ) Jest to podstawowy konstruktor przeznaczony do inicjowania obiektów na etapie ich deklaracji czy też tworzenia. Argumenty określają zwykle wartości jakie mają być przypisane określonym polom obiektu. < Konstruktorów głównych może być więcej, mogą one zawierać również parametru domyślne. < Szczególnym przypadkiem jest konstruktor posiadający tylko parametry domyślne, staje się on wtedy konstruktorem domyślnym. Załóżmy istnienie konstruktora klasy A o następującej deklaracji prototypowej: A( int a, float b, char * c = NULL ) Zostanie on wykorzystany do zainicjowania poniższych obiektów: A obj1( 2, 3.4, "Ala"); A obj2( 1, 0.0 ); A obj3( 5, 5.5, "Pięć"); Dwie przykładowe wersje konstruktora ogólnego klasy Rectangle: Rectangle::Rectangle( float width, float height ) : width( width ), height( height ) Rectangle::Rectangle( float side ) : width( side ), height( side ) Copyright Roman Simiński 18

Klasa Rectangle raz jeszcze funkcje inline class Rectangle public : ; void setwidth( float width ) Rectangle::width = width; float getwidth() const return width; Wprowadzenie do programowania w C++ funkcje inline Funkcje zdefiniowane wewnątrz definicji klasy są traktowane niejawnie jako funkcje inline (rozwijane w miejscu wywołania). < Funkcje inline nie są wywoływane w sposób klasyczny ich kod jest umieszczany w miejscu wywołania i w rzeczywistości nie są one wywoływane. < Funkcje inline są preferowanym w C++ zamiennikiem makr definiowanych z wykorzystaniem #define. Jak zadeklarować funkcje jako inline poza zasięgiem deklaracji klasy? class Rectangle public : ; void setwidth( float width ); float getwidth() const; inline void Rectangle::setWidth( float width ) Rectangle::width = width; inline float Rectangle::getWidth() const return width; < Jeżeli funkcje inline mają być wykorzystywane modułach umożliwiających kompilacje rozłączną, definicja funkcji powinna wystąpić w miejscu jej zwyczajowej deklaracji w odpowiednim pliku nagłówkowym. Copyright Roman Simiński 19

Funkcje inline za i przeciw Wprowadzenie do programowania w C++ funkcje inline Kod wielokrotnie wykorzystujący pewną funkcję inline: może działać szybciej brak narzutu czasowego związanego z organizacją wywołania funkcji i powrotu z podprogramu; będzie dłuższy, zawiera bowiem rozwinięcia ciała funkcji w miejscu jej każdorazowego wywołania. Specyfikacja ze słowem kluczowym inline to tylko rekomendacja dla kompilatora niektórych funkcji nie można w pełni rozwinąć i będą one wywoływane klasycznie (np. rekurencyjne). < Mechanizm funkcji zadeklarowanych jako inline przeznaczony jest do optymalizacji małych, prostych i często wykorzystywanych funkcji. < Dobrym zastosowaniem funkcji inline jest implementacja akcesorów i modyfikatorów realizujących dostęp do prywatnych pól klasy. W porównaniu z makrami funkcje inline zapewniają kontrole typów i wychwytywanie błędów na etapie kompilacji. Copyright Roman Simiński 20

Wprowadzenie do programowania w C++ klasa Square w osobnym pliku Klasa Square w osobnym module programu Języki C i C++ nie oferują zdefiniowanej syntaktycznie modularyzacji. Jednak program może się składać z kompilowanych oddzielnie części zwanych właśnie modułami łączonych potem przez konsolidator (wraz z bibliotekami) w plik wykonywalny. Przyjęta konwencja budowania modułów zakłada oddzielenie części publicznej modułu od części implementacyjnej. Plik nagłówkowy klasy Square square.hpp #ifndef _SQUARE_HPP_ #define _SQUARE_HPP_ // Deklaracja klasy class Square public : Square(); Square( float side ); Square( const Square & othersquare ); void setside( float side ); float getside() const; float area() const; private: float side; ; // Definicja metod inline inline void Square::setSide( float side ) Square::side = side; inline float Square::getSide() const return side; #endif Plik implementacyjny klasy Square square.cpp #include "square.hpp" Square::Square() : side( 0 ) Square::Square( float side ) : side( side ) Square::Square( const Square & othersquare ) : side( othersquare.side ) float Square::area() const return side * side; Copyright Roman Simiński 21

Wprowadzenie do programowania w C++ klasa Square w osobnym pliku Plik programu wykorzystującego klasę Square testsqr.cpp #include <iostream> using namespace std; #include "square.hpp" int main() Square mygarden( 100 ); cout << endl << "Powierzchnia mojego ogrodu : " << mygarden.area(); return EXIT_SUCCESS; Koncepcja kompilacji rozłącznej Celem kompilacji rozłącznej jest minimalizacja liczby niezbędnych kompilacji, co wpływa na ograniczenie czasu kompilacji programu. Kompilacja rozłączna zarys koncepcji #include square.cpp square.hpp Kompilacja pliku square.cpp Kompilacja pliku testsqr.cpp square.o (square.obj) testsqr.o (testsqr.obj) Konsolidacja Program wykonywalny #include testsqr.cpp Pliki programu Pliki poœrednie Kompilacja rozłączna przebieg szczegółowy square.cpp Biblioteki.lib.o obj Preprocesor Kompilator Kompilacja pliku square.cpp Kompilacja pliku testsqr.cpp Preprocesor Kompilator square.o (square.obj) testsqr.o (testsqr.obj) Konsolidator Program wykonywalny square.hpp testsqr.cpp Jaka nazwa? Pliki nag³ówkowe bibliotek Pliki w³asne Pliki poœrednie Pliki bibliotek standardowych Copyright Roman Simiński 22

Organizacja kompilacji rozłącznej Wprowadzenie do programowania w C++ kompilacja rozłączna Manualne zarządzanie kompilacją rozłączną (na przykładzie Unixa) Kompilacja i konsolidacja pewnego programu t.cpp: $ cc t.cpp Wywołanie to spowoduje: 1. kompilacje programu, 2. wygenerowanie pliku pośredniego t.o (w przypadku braku błędu) 3. połączenie t.o z plikami bibliotek i generacja i wynikowego pliku a.out. Użycie flagi -o umożliwia określenie nazwy pliku wynikowego $ cc t.cpp o test Wymuszenie kompilacji bez łączenia (opcja -c) $ cc -c t.cpp W przypadku braku błędów powstanie plik pośredni t.o Kompilujemy oddzielnie pliki square.cpp i testsqr.cpp $ cc -c square.cpp $ cc -c testsqr.cpp Otrzymujemy pliki square.o i testsqr.o, łączymy je w program wykonywalny o nazwie tests: $ cc square.o testsqr.o -o tests W przypadku modyfikacji pliku testsqr.cpp wystarczy: $ cc -c testsqr.cpp $ cc square.o testsqr.o -o tests Jak zautomatyzować proces kompilacji rozłącznej? make program realizujący niezbędne kompilacje w oparciu o reguły zdefiniowane w pliku sterującym (domyślna nazwa Makefile). < Plik ten opisuje zależności pomiędzy modułami programu oraz określa jaki wywołania powinny zostać wykonane dla każdego z modułów. < Program make sprawdza czasy modyfikacji plików źródłowych i docelowych i przeprowadza jedynie niezbędne kompilacje. Copyright Roman Simiński 23

Przykładowy Makefile Wprowadzenie do programowania w C++ kompilacja rozłączna tests : square.o testsqr.o cc square.o testsqr.o o test square.o : square.cpp square.hpp cc -c square.cpp testsqr.o : testsqr.cpp square.hpp cc -c testsqr.cpp Pliki dla programu make bywają często złożone, mogą zawierać wiele różnych konstrukcji Zarządzanie kompilacją przez środowisko programistyczne Większość środowisk programistycznych oferuje możliwość budowania projektów. Projekt określa przynajmniej: pliki źródłowe i pomocnicze wchodzące w skład programu, lokalizację bibliotek, plików nagłówkowych, opcje kompilacji, typ kodu wynikowego, oraz inne, zależne od implementacji, cechy i parametry programu. Definiowanie projektu: Dev-C++ < Projekty zwykle stanowią podstawę do wygenerowania pliku dla programu make. Copyright Roman Simiński 24

Wprowadzenie do programowania w C++ kompilacja rozłączna Plik Makefile dla programu tests.cpp (Dev-C++) # Project: tests # Makefile created by Dev-C++ 4.9.8.0 CPP = g++.exe CC = gcc.exe WINDRES = windres.exe RES = OBJ = square.o testsqr.o $(RES) LINKOBJ = square.o testsqr.o $(RES) LIBS = -L"C:/DEV-CPP/lib" INCS = -I"C:/DEV-CPP/include" CXXINCS = -I"C:/DEV-CPP/include/c++" -I"C:/DEV-CPP/include/c++/mingw32" - I"C:/DEV-CPP/include/c++/backward" -I"C:/DEV-CPP/include" BIN = tests.exe CXXFLAGS = $(CXXINCS) CFLAGS = $(INCS).PHONY: all all-before all-after clean clean-custom all: all-before tests.exe all-after clean: clean-custom rm -f $(OBJ) $(BIN) $(BIN): $(LINKOBJ) $(CPP) $(LINKOBJ) -o "tests.exe" $(LIBS) square.o: square.cpp $(CPP) -c square.cpp -o square.o $(CXXFLAGS) testsqr.o: testsqr.cpp $(CPP) -c testsqr.cpp -o testsqr.o $(CXXFLAGS) Definiowanie projektu: Borland C++ Builder Makefile wygenerowany przez Builder a dla powyższego projektu liczy blisko 200 linii! Copyright Roman Simiński 25

Wprowadzenie do programowania w C++ kompilacja rozłączna Definiowanie projektu: Borland C++ 3.1 Ułatwienia w zarządzaniu kodem programu: Dev-C++ Ułatwienia w zarządzaniu kodem programu: Borland C++ Builder Copyright Roman Simiński 26

Hierarchia klas opisujących pojazdy class Pojazd ; class Samochod : public Pojazd ; class Autobus: public Samochod ; class Ciezarowka: public Samochod ; Hierarchia klas opisujących łodzie class Lodka ; class Zaglowka : public Lodka ; class Motorowka : public Lodka ; class Kuter: public Lodka ; Wprowadzenie do programowania w C++ dziedziczenie Klasa opisu amfibii dziedziczenie po dwóch przodkach class Amfibia : public Samochod, public Lodka ; Klasa opisu Jachtu problem z dziedziczenie po dwóch przodkach class Jacht: public Zaglowka, public Motorowka ; Dziedziczenie po jednym przodku dziedziczenie jednobazowe Dziedziczenie po wielu przodkach dziedziczenie wielobazowe Copyright Roman Simiński 27

Anatomia dziedziczenia na przykładzie class Point public : Point() : x( 0 ), y( 0 ) Point( int x, int y ) : x( x ), y( y ) void setx( int x ) Point::x = x; int getx() const return x; void sety( int y ) Point::y = y; int gety() const return y; private: int x, y; ; Wprowadzenie do programowania w C++ dziedziczenie class Point3D : public Point public : Point3D() : Point(), z( 0 ) Point3D( int x, int y, int z ) : Point( x, y ), z( z ) void setz( int z ) Point3D::z = z; int getz() const return z; private: int z; ; class Pixel : public Point public : Pixel() : Point(), color( 0 ) Pixel( int x, int y, int color ) : Point( x, y ), color( color ) void setcolor( int z ) Pixel::color = color; int getcolor() const return color; void put() const // Funkcja wyświetl. piksela z odpowiedniej bibl. graficznej, np.: putpixel( getx(), gety(), color ); private: int color; ; int main() Point p1( 10, 12 ); Point3D p2( 2, 5, 4 ); cout << endl << "Punkt 2D ma wspolrzedne" << endl; cout << "x = " << p1.getx() << endl; cout << "y = " << p1.gety() << endl; cout << endl << "Punkt 3D ma wspolrzedne" << endl; cout << "x = " << p2.getx() << endl; cout << "y = " << p2.gety() << endl; cout << "z = " << p2.getz() << endl; return 0; Copyright Roman Simiński 28

Dziedziczenie w trybie publicznym Wprowadzenie do programowania w C++ dziedziczenie Dziedziczenie w trybie publicznym zachowuje widoczność pól określoną w klasie bazowej. class Point3D : public Point Aktywowanie konstruktora klasy bazowej Konstruktor klasy pochodnej aktywuje konstruktor klasy bazowej umieszczony na liście inicjalizacyjnej, odbywa się to przed wywołaniem ciała konstruktora. Point3D() : Point(), z( 0 ) < W klasie pochodnej definiujemy metody do obsługi nowych pól, obsługę pól odziedziczonych realizujemy z wykorzystaniem metod odziedziczonych. Redefinicja metod i pola statyczne class ScrPixel : public Pixel public : ScrPixel() : Pixel() ScrPixel( int x, int y, int color ) : Pixel( x, y, color ) ; void setx( int x ) Point::setX( ( x >= minx && x <= maxx )? x : 0 ); void sety( int y ) Point::setY( ( y >= miny && y <= maxy )? y : 0 ); static int minx, miny, maxx, maxy; int ScrPixel::minx = 0; int ScrPixel::miny = 0; int ScrPixel::maxx = 800; int ScrPixel::maxy = 600; ScrPixel pixel; ScrPixel::maxx = screen.getmaxx(); ScrPixel::maxy = screen.getmaxy(); pixel.setx( 300 ); pixel.sety( 200 ); pixel.put(); Copyright Roman Simiński 29

Pola statyczne Wprowadzenie do programowania w C++ dziedziczenie Pola statyczne dla danej klasy występują tylko raz, są współdzielone przez wszystkie obiekty tej klasy. Istnieją nawet wtedy, gdy nie został utworzony żaden obiekt klasy. < Pola statyczne muszą być zdefiniowane poza klasą, nadaje się im tedy wartość początkową. int ScrPixel::minx = 0; int ScrPixel::miny = 0; int ScrPixel::maxx = 800; int ScrPixel::maxy = 600; Do pól statycznych klasy można odwoływać się bez obiektu: ScrPixel::maxx = screen.getmaxx(); < Pola statyczne stanowią wspólną, współdzieloną pamięć wszystkich obiektów danej klasy. < Wykorzystywane są do zapamiętywania informacji, które są wspólne dla wszystkich obiektów i nie muszą być pamiętane osobno w każdym z obiektów. Redefinicja metod w klasie pochodnej class Point void setx( int x ) Point::x = x; ; class ScrPixel : public Pixel void setx( int x ) Point::setX( ( x >= minx && x <= maxx )? x : 0 ); ; W klasie pochodnej można zmienić sposób działania metody odziedziczonej poprzez jej redefinicję. Do metody odziedziczonej można dalej odwoływać się stosując prefiks w postaci nazwy_ klasy_bazowej:: < Redefinicję metody w klasie pochodnej stosujemy wtedy, gdy nie odpowiada nam działanie metody odziedziczonej. Można napisać własną implementację metody, opcjonalnie posługując się również metodą odziedziczoną. Copyright Roman Simiński 30

Składowe chronione specyfikacja protected Wprowadzenie do programowania w C++ dziedziczenie W klasie pochodnej nie ma bezpośredniego dostępu do pól prywatnych klasy bazowej. class Pixel : public Point public : void put() const putpixel( getx(), gety(), color ); ; Przewidując, że pewna klasa będzie wykorzystywana jako klasa bazowa, można zadeklarować jej składowe (pola i metody) jako chronione protected: Składowe zadeklarowane jako protected są dostępne dla obiektów wszystkich klas pochodnych (tak jak składowe public). Składowe zadeklarowane jako protected są niedostępne dla obiektów innych, niezaprzyjaźnionych klas (tak jak składowe private). < Specyfikator protected działa jak private, z tym wyjątkiem, że obiekty klas pochodnych otrzymują dostęp do składowych protected klasy bazowej. Deklaracja pól x i y jako chronionych: class Point public : protected: int x, y; ; class Pixel : public Point public : void put() const putpixel( x, y, color ); // Dozwolone bezpośrednie odwołanie do x i y ; Point p; p.x = 10; // Błąd, składowa x jest chroniona! Copyright Roman Simiński 31

Metody (funkcje) wirtualne Wprowadzenie do programowania w C++ metody wirtualne Dziedziczenie klasy pochodne redefiniują metody class Robot public: Robot() void whoareyou() cout << endl << "UR : Universal robot"; void dowork() cout << endl << "UR : working"; ; class Welder : public Robot // Spawacz public: Welder() : Robot() void whoareyou() cout << endl << "WR : Welder robot"; void dowork() cout << endl << "WR : working"; ; class Varnisher : public Robot // Lakiernik public: Varnisher() : Robot() void whoareyou() cout << endl << "VR : Varnisher robot"; void dowork() cout << endl << "VR : working"; ; class Polisher : public Robot // Polernik public: Polisher() : Robot() void whoareyou() cout << endl << "PR : Polisher robot"; void dowork() cout << endl << "PR : working"; ; int main() const int numofrobots = 3; // Liczba robot w na ta śmie Welder w; // Obiekt sterujący robotem spawaczem Varnisher v; // Obiekt sterujący robotem lakiernikiem Polisher p; // Obiekt sterujący robotem polernikiem Robot * robots[ numofrobots ] = &w, &v, &p ; // Linia robot w for( int i = 0; i < numofrobots; i++ ) // Roboty przedstawcie się robots[ i ]->whoareyou(); for( int i = 0; i < numofrobots; i++ ) // Roboty do roboty! robots[ i ]->dowork(); return 0; Wyniki działania programu: Copyright Roman Simiński 32

Wprowadzenie do programowania w C++ metody wirtualne Wprowadzamy metody (funkcje) wirtualne słowo kluczowe virtual class Robot public: Robot() virtual void whoareyou() cout << endl << "UR : universal robot"; virtual void dowork() cout << endl << "UR : working"; ; Wyniki działania programu Inny przykład void showkindofrobot( Robot & robot ) robot.whoareyou(); int main() Welder w; Varnisher v; Polisher p; Bez metod wirtualnych Z metodami wirtualnym showkindofrobot( w ); showkindofrobot( v ); showkindofrobot( p ); Przypisanie konkretnego ciała funkcji do wywołania to wiązanie (ang. binding). W C++ występują dwa rodzaje wiązania: Wczesne wiązanie (ang. early binding) polega na przypisaniu konkretnej funkcji każdemu wywołaniu już na etapie kompilacji programu. Inna nazwa wiązanie statyczne (ang. static binding). Późne wiązanie (ang. late binding) polega na przypisaniu konkretnej funkcji każdemu wywołaniu dopiero na etapie wykonania programu, w zależności od typu obiektu. Inna nazwa dynamiczne wiązanie (ang. dynamic binding) Musi istnieć mechanizm określania typu obiektu w trakcie wykonania programu i wywoływania odpowiedniej funkcji. < Wykorzystanie słowa virtual w deklaracji funkcji powoduje, iż będzie ona wiązana dynamicznie. Copyright Roman Simiński 33

Wprowadzenie do programowania w C++ metody wirtualne Jak kompilator generuje kod w przypadku wiązania statycznego? void showkindofrobot( Robot & robot ) robot.whoareyou(); showkindofrobot( v ); Wi¹zanie statyczne (wczesne) : adres funkcji ustalany jest w trakcie kompilacji, na podstawie klasy obiektu wystêpuj¹cego w deklaracji Robot * robots[ 3 ]; robots[ 0 ] = &w; robots[ 1 ] = &v; robots[ 2 ] = &p; robots[ 0 ]->dowork(); robots 0 1 2 Ilustracja wywo³ania metod (funkcji) niewirtualnych Robot Robot::whoAreYou() Robot::doWork() Obiekt : w Welder Welder::whoAreYou() Welder::doWork() Obiekt : v =robot Varnisher Varnisher::whoAreYou() Varnisher::doWork() Obiekt : p Polisher Polisher::whoAreYou() Polisher::doWork() & Segment kodu programu Robot::whoAreYou() push bp mov bp,sp push si Robot::doWork() push bp mov bp,sp push si Welder::whoAreYou() push bp mov bp,sp push si Welder::doWork() push bp mov bp,sp push si Varnisher::whoAreYou() push bp mov bp,sp push si Varnisher::doWork() push bp mov bp,sp push si Polisher::whoAreYou() push bp mov bp,sp push si Polisher::doWork() push bp mov bp,sp push si Copyright Roman Simiński 34

Wprowadzenie do programowania w C++ metody wirtualne Jak kompilator generuje kod w przypadku wiązania dynamicznego? void showkindofrobot( Robot & robot ) robot.whoareyou(); showkindofrobot( v ); Wi¹zanie dynamiczne (póÿne): adres funkcji ustalany jest w trakcie wykonania programu, na podstawie klasy obiektu wskazywanego jawnie lub przez referencjê robots[ 0 ] = &w; robots[ 1 ] = &v; robots[ 2 ] = &p; robots[ 0 ]->dowork(); robots 0 1 2 Robot vptr Obiekt : w Welder vptr Obiekt : v Varnisher vptr Obiekt : p Polisher vptr Ilustracja wywo³ania metod (funkcji) wirtualnych & =robot vtab whoareyou dowork vtab whoareyou dowork vtab whoareyou dowork vtab whoareyou dowork Segment kodu programu Robot::whoAreYou() push bp mov bp,sp push si Robot::doWork() push bp mov bp,sp push si Welder::whoAreYou() push bp mov bp,sp push si Welder::doWork() push bp mov bp,sp push si Varnisher::whoAreYou() push bp mov bp,sp push si Varnisher::doWork() push bp mov bp,sp push si Polisher::whoAreYou() push bp mov bp,sp push si Polisher::doWork() push bp mov bp,sp push si Copyright Roman Simiński 35

Referencje w akcji Wprowadzenie do programowania w C++ funkcje operatorowe Referencja jest synonimem (alternatywną nazwą) pewnego obiektu w pamięci operacyjnej. Każda operacja wykonana na referencji będzie również wykonana na obiekcie, do którego referencja się odnosi. Zmienne referencyjne int num = 10; int & numref = num; // Inicjalizacja zmiennej referencyjnej numref = 5; cout << "num num = 0; cout << "num cout << "&num = " << num << endl << "numref = " << numref << endl; = " << num << endl << "numref = " << numref << endl; = " << &num << endl << "&numref = " << &numref << endl; Wyniki działania programu Pamiêc operacyjna num 10 numref < Referencja nie jest wskaźnikiem! < Zmienna referencyjna musi być zainicjowana, ustala się wtedy obiekt do którego referencja się odnosi i to przypisanie nie może ulec zmianie. Uwaga: int num1 = 10, num2 = 20; int numref = num1; numref = num2; // Co spowoduje to przypisanie? Czym wolno inicjować obiekty referencyjne Wartością inicjującą referencję może być l-wartość odpowiedniego typu. Wartością inicjującą referencję do obiektu stałego może być r-wartość lub l-wartość niezgodnego typu. unsigned char uc; double d1 = 1.0, d2 = 2.0; int & iref = 100; char & cref = uc; int & dref = d1 + d2; const int & iref = 100; // OK const char & cref = uc; // OK const int & dref = d1 + d2; // OK... // Błąd, to nie jest l-wartość! // Błąd, l-wartość niezgodnego typu! // Błąd, to nie jest l-wartość! Copyright Roman Simiński 36

Wprowadzenie do programowania w C++ funkcje operatorowe Wykorzystanie referencji przy przekazywaniu parametrów int a = 5, b = 10; swap( a, b); void swap( int x, int y ) int temp = x; x = y; y = temp; Zamień wartości tak by po wykonaniu a == 10 oraz b == 5. To nie będzie działać przekazywanie parametrów przez wartość. void swap( int * x, int * y ) int temp = *x; *x = *y; *y = temp; void swap( int & x, int & y ) int temp = x; x = y; y = temp; To będzie działać - wykorzystanie wskaźników, ale wywołanie musi mieć postać: swap( &a, &b ); To będzie działać - wykorzystanie referencji, wywołanie ma postać: swap( a, b ); Copyright Roman Simiński 37

Wprowadzenie do programowania w C++ funkcje operatorowe Funkcje operatorowe, operatory przeciążone Problem Należy napisać program realizujący obliczenia dla układów prądu sinusoidalnie zmiennego. Do realizacji tych obliczeń wykorzystuje się liczby zespolone do tego celu należy zbudować klasę Complex. class Complex public: // Konstruktory Complex(); Complex( double re, double im = 0 ); // Akcesory double getreal() const; double getimag() const; void setreal( double newval ); void setimag( double newval ); private: double real; // Część rzeczywista double imag; // Część urojona ; Implementacja funkcji składowych Complex::Complex() : real( 0 ), imag( 0 ) Complex::Complex( double re, double im ) : real( re ), imag( im ) double Complex::getReal() const return real; double Complex::getImag() const return imag; void Complex::setReal( double newval ) real = newval; void Complex::setImag( double newval ) imag = newval; Copyright Roman Simiński 38

Jak wykorzystać klase Complex? Wprowadzenie do programowania w C++ funkcje operatorowe Complex z1; // Konstruktor: z1.complex(); Complex z2( 2 ); // Konstruktor: z2.complex( 2 ); parametr domyślny! complex z3( 1, 1 ); // Konstruktor: z2.complex( 1, 1 ); // Dodawanie liczb zespolonych wersja siermiężna z1.setreal( z2.getreal() + z3.getreal() ); z1.setimag( z2.getimag() + z3.getimag() ); Czy nie można tak: // Dodawanie liczb zespolonych wersja poprawiona z1 = z2 + z3; Jak to zrobić krok pierwszy Rozszerzamy klasę Complex o przeciążony operator przypisania class Complex public: Complex & operator = ( const Complex & z ); ; Implementacja operatora przypisania Complex & Complex::operator = ( const Complex & z ) real = z.real; // Lub setreal( z.getreal() ); imag = z.imag; // Lub setimag( z.getimag() ); return *this; Jak to działa? z1 = z2; // z1.operator = ( z2 ); z3 = z1; // z3.operator = ( z1 ); z1 = z2 = z3; // z1.operator = ( z2.operator = ( z3 ) ); A co gdy jest tak? z1 = z1; // z1.operator = ( z1 ); Poprawiona wersja operatora przypisania Complex & Complex::operator = ( const Complex & z ) if( &z!= this ) real = z.real; imag = z.imag; return *this; < this w obrębie definicji każdej funkcji składowej klasy występuje wskaźnik this. Wskazuje on zawsze na obiekt, dla którego została wywołana dana funkcja składowa. W tym przykładzie przeciążanie operatora = nie jest konieczne. Copyright Roman Simiński 39

Jak to zrobić krok drugi Wprowadzenie do programowania w C++ funkcje operatorowe Rozszerzamy klasę Complex o przeciążony operator dodawania class Complex public: Complex operator + ( const Complex & z ); ; Implementacja operatora dodawania Complex Complex::operator + ( const Complex & z ) Complex tmp; // Obiekt tymczasowy do przechowania sumy tmp.real = real + z.real; // Lub tmp.setreal( getreal() + z.getreal() ); tmp.imag = imag + z.imag; // Lub tmp.setimag( getimag() + z.getimag() ); return tmp; Jak to działa? z1 + z2; // z1.operator + ( z2 ); Razem z operatorem = z1 = z2 + z3; // z1.operator = ( z2.operator + ( z3 ) ); Krótsza implementacja operatora dodawania Complex Complex::operator + ( const Complex & z ) return Complex( real + z.real, imag + z.imag ); Dlaczego rezultat operatora + nie jest referencją? < W C i C++ rezultatem funkcji nie powinien być wskaźnik ani referencja do zmiennych automatycznych funkcji. Te lokowane są zwykle na stosie i po zakończeniu działania funkcji przestają istnieć. Implementacja operatora odejmowania ( binarny minus ) Complex Complex::operator - ( const Complex & z ) return Complex( real - z.real, imag - z.imag ); Implementacja operatora zmiany znaku ( unarny minus ) Complex Complex::operator - () return Complex( - real, - imag ); z2 = -z1; // z2.operator = ( z1.operator - () ); z1 = z2 - z3; // z1.operator = ( z2.operator - ( z3 ) ); Copyright Roman Simiński 40

Przeciążanie operatorów ++ i -- z1++; ++z1; --z2; z2--; Wprowadzenie do programowania w C++ funkcje operatorowe Do wersji 3.0 języka C++ nie istniało rozróżnienie pomiędzy operatorami w wersji przedrostkowej i przyrostkowej. class Complex public: Complex & operator ++ (); Complex operator ++ ( int ); Complex & operator -- (); Complex operator -- ( int ); ; // Postać przedrostkowa // Postać przyrostkowa // Postać przedrostkowa // Postać przyrostkowa Implementacja operatorów przedrostkowych Complex & Complex::operator ++ () ++real; ++imag; return *this; Complex & Complex::operator -- () --real; --imag; return *this; Implementacja operatorów przyrostkowych Complex Complex::operator ++ ( int ) Complex copy; copy = *this; ++real; ++imag; return copy; // Zapamiętaj w copy wartość obiektu przed inkrementacją // Zwr ć kopię wartości obiektu z przed inkrementacji Complex Complex::operator -- ( int ) Complex copy( *this ); // Tu nieco kr cej -- konstruktor kopiujący --real; --imag; return copy; Wykorzystanie operatorów przedrostkowych i przyrostkowych z1 = ++z2; // zi.operator = ( z2.operator++() ); z1 = z2++; // zi.operator = ( z2.operator++( 0 ) ); Copyright Roman Simiński 41