Programowanie obiektowe

Slides:



Advertisements
Podobne prezentacje
Programowanie obiektowe
Advertisements

Przekazywanie argumentów
Programowanie strukturalne i obiektowe C++ Przeładowanie operatorów Robert Nowak.
Temat 2: Podstawy programowania Algorytmy – 1 z 2 _________________________________________________________________________________________________________________.
Równowaga chemiczna - odwracalność reakcji chemicznych
Tworzenie odwołania zewnętrznego (łącza) do zakresu komórek w innym skoroszycie Możliwości efektywnego stosowania odwołań zewnętrznych Odwołania zewnętrzne.
Wyszukiwanie informacji w Internecie. Czym jest wyszukiwarka? INTERNET ZASOBY ZAINDEKSOWANE PRZEZ WYSZUKIWARKI Wyszukiwarka to mechanizm, który za pomocą.
Excel 2007 dla średniozaawansowanych zajęcia z dnia
Cel analizy statystycznej. „Człowiek –najlepsza inwestycja”
FORMAT WYMIANY DANYCH GEODEZYJNYCH TANAGO. TANGO V. 1.
 Czasem pracy jest czas, w którym pracownik pozostaje w dyspozycji pracodawcy w zakładzie pracy lub w innym miejscu wyznaczonym do wykonywania pracy.
EWALUACJA JAKO ISTOTNY ELEMENT PROJEKTÓW SYSTEMOWYCH Sonia Rzeczkowska.
Zmienne losowe Zmienne losowe oznacza się dużymi literami alfabetu łacińskiego, na przykład X, Y, Z. Natomiast wartości jakie one przyjmują odpowiednio.
Analiza tendencji centralnej „Człowiek – najlepsza inwestycja”
Algorytmy Informatyka Zakres rozszerzony
KOMBINATORYKA.
Finansowanie wybranych działań w parkach narodowych przy udziale środków funduszu leśnego - zakres merytoryczny Warszawa, 06 kwietnia 2016 r.
Menu Jednomiany Wyrażenia algebraiczne -definicja Mnożenie i dzielenie sum algebraicznych przez jednomian Mnożenie sum algebraicznych Wzory skróconego.
Metody sztucznej inteligencji - Technologie rozmyte i neuronowe 2015/2016 Perceptrony proste nieliniowe i wielowarstwowe © Kazimierz Duzinkiewicz, dr hab.
Definiowanie i planowanie zadań typu P 1.  Planowanie zadań typu P  Zadania typu P to zadania unikalne służące zwykle dokonaniu jednorazowej, konkretnej.
1 Definiowanie i planowanie zadań budżetowych typu B.
Moduł II. Obszar formułowania Programów i Projektów.
Język Java Paweł Rajba
Dziedziczenie, polimorfizm, Interfejsy
Test analizy wariancji dla wielu średnich – klasyfikacja pojedyncza
Programowanie Obiektowe – Wykład 1
Schematy blokowe.
Kurs języka C++ – wykład 2 ( )
DEFINICJA I ZASTOSOWANIE W JĘZYKU HASKELL
ORGANIZACJA.
Ciąg arytmetyczny Opracowały : Iwona Głowacka i Małgorzata Jacek.
MATEMATYCZNE MODELOWANIE PROCESÓW BIOTECHNOLOGICZNYCH
Liczby pierwsze.
Akademia C# - Lab2 Zmienne, instrukcje warunkowe, pętle, debugger,
Kurs języka C++ – wykład 6 ( )
Rekursje Tak jak w innych językach funkcje mogą odwoływać się same do siebie Możemy regulować głębokość przed stwierdzeniem błędu (MaxRecursion, $RecursionLimit,
(c) Krzysztof Barteczko 2014
Akademia C# lab. 9 Zdarzenia i delegaty.
Programowanie obiektowe Wykład 10
Programowanie Obiektowe – Wykład 2
Programowanie obiektowe
Wstęp do Informatyki - Wykład 3
Elementy analizy matematycznej
Optymalizacja programów Open-Source
Lekcja 1 – Hello World! Visual Studio, coś łatwego na początek 
Programowanie obiektowe
Materiały pochodzą z Platformy Edukacyjnej Portalu
Kurs języka C++ – wykład 13 ( )
Elementy fizyki kwantowej i budowy materii
PROGRAMY DO KONTROLI RODZICIELSKIEJ
Programowanie obiektowe
Bezpieczeństwo dostępu do danych w systemie Windows
Języki programowania.
Tensor naprężeń Cauchyego
Instrukcje wyboru.
Język C/C++ Funkcje.
Koszyk danych.
Podstawy informatyki Zygfryd Głowacz.
Strukturalne wzorce projektowe
Zmienne i typy danych w C#
Proste obliczenia w arkuszu kalkulacyjnym
Zdarzenia (eventy) Zdarzenia służą do powiadomienia użytkownika, gdy w używanej klasie dojdzie do pewnych wydarzeń zdefiniowanych przez twórcę klasy.
Implementacja rekurencji w języku Haskell
Znajdowanie liczb pierwszych w zbiorze
Język C++ Preprocesor Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła.
Język C++ Operatory Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła.
Prawa ruchu ośrodków ciągłych c. d.
Program na dziś Wprowadzenie Logika prezentacji i artykułu
Autor: Magdalena Linowiecka
Projektowanie systemów informatycznych Wykład 3 – Obiekt a klasa
Zapis prezentacji:

Programowanie obiektowe Klasy w C++

Wstęp Klasa jest kluczową koncepcją języka C++, realizującą abstrakcję danych na bardzo wysokim poziomie. Odpowiednio zdefiniowane klasy stawiają do dyspozycji użytkownika wszystkie istotne mechanizmy programowania obiektowego: ukrywanie informacji, dziedziczenie, polimorfizm z wiązaniem późnym, a także szablony klas i funkcji. Klasa jest deklarowana i definiowana z jednym z trzech słów kluczowych: class, struct i union. Elementami składowymi klasy mogą być struktury danych różnych typów, zarówno podstawowych, jak i zdefiniowanych przez użytkownika, a także funkcje dla operowania na tych strukturach. Dostęp do elementów klasy określa zbiór reguł dostępu.

Deklaracja i definicja klasy Klasa jest typem definiowanym przez użytkownika. Deklaracja klasy składa się z nagłówka, po którym następuje ciało klasy, ujęte w parę nawiasów klamrowych; po zamykającym nawiasie klamrowym musi wystąpić średnik, ewentualnie poprzedzony listą zmiennych. W nagłówku klasy umieszcza się słowo kluczowe class (lub struct albo union), a po nim nazwę klasy, która od tej chwili staje się nazwą nowego typu. Klasa może być deklarowana: Na zewnątrz wszystkich funkcji programu. Zakres widzialności takiej klasy rozciąga się na wszystkie pliki programu. Wewnątrz definicji funkcji. Klasę taką nazywa się lokalną, ponieważ jej zakres widzialności nie wykracza poza zasięg funkcji. Wewnątrz innej klasy. Klasę taką nazywa się zagnieżdżoną, ponieważ jej zakres widzialności nie wykracza poza zasięg klasy zewnętrznej. Deklaracji klas nie wolno poprzedzać słowem kluczowym static.

Przykłady deklaracji Przykładowe deklaracje klas mogą mieć postać: class Pusta {}; class Komentarz { /* Komentarz */}; class Niewielka { int n; }; Wystąpienia klasy deklaruje się tak samo, jak zmienne innych typów, np. Pusta pusta1, pusta2; Niewielka nw1, nw2; Niewielka* wsk = &nw1; Zmienne pusta1, pusta2, nw1, nw2 nazywają się obiektami, zaś wsk jest wskaźnikiem do typu Niewielka, zainicjowanym adresem obiektu nw1. Klasy w rodzaju Pusta i Komentarz używa się często jako klasy-makiety podczas opracowywania programu.

Specyfikatory (modyfikatory) dostępu Deklaracje elementów składowych klasy można poprzedzić etykietą public:, protected:, lub private:. Jeżeli sekwencja deklaracji elementów składowych nie jest poprzedzona żadną z tych etykiet, to kompilator przyjmuje domyślną etykietę private:. Oznacza to, że dana składowa może być dostępna jedynie dla funkcji składowych i tzw. funkcji zaprzyjaźnionych klasy, w której jest zadeklarowana. Wystąpienie etykiety public: oznacza, że występujące po niej nazwy deklarowanych składowych mogą być używane przez dowolne funkcje, a więc również takie, które nie są związane z deklaracją danej klasy. Znaczenie etykiety protected: - później. Ze względu na sterowanie dostępem do składowych klasy, słowa kluczowe public, protected i private nazywa się specyfikatorami dostępu.

Przykład #include <iostream> #include <conio.h> using namespace std; class Niewielka { public: int n; void komunikat() { cout<<"Tu jestesmy"; } }; void main() { Niewielka nw1; nw1.n = 5; cout<<"nw1.n="<<nw1.n<<endl; cout<<"komunikat="; nw1.komunikat(); getch();

Definicja klasy Jeżeli klasa zawiera funkcje składowe, to ich deklaracje muszą wystąpić w deklaracji klasy. Funkcje składowe mogą być jawnie deklarowane ze słowami kluczowymi inline, static i virtual; nie mogą być deklarowane ze słowem kluczowym extern. W deklaracji klasy można również umieszczać definicje krótkich (1-2 instrukcje) funkcji składowych; są one wówczas traktowane przez kompilator jako funkcje rozwijalne, tj. tak, jakby były poprzedzone słowem kluczowym inline. W programach jednoplikowych dłuższe funkcje składowe deklaruje się w nawiasach klamrowych zawierających ciało klasy, zaś definiuje się bezpośrednio po zamykającym nawiasie klamrowym. Deklaracja klasy wraz z definicjami funkcji składowych (i ewentualnie innymi wymaganymi definicjami) stanowi definicję klasy.

Przykład definicji klasy #include <iostream> #include <conio.h> using namespace std; class Punkt { public: int x,y; void init(int a, int b) { x = a; y = b; } void ustaw(int, int); }; void Punkt::ustaw(int a, int b) x = x + a; y = y + b; int main() { Punkt punkt1; punkt1.init(1,1); cout << punkt1.x << endl; cout << punkt1.y << endl; punkt1.ustaw(10,15); getch(); return 0;

Konstruktory i destruktory Konstruktory i destruktory należą do grupy specjalnych funkcji składowych. Grupa ta obejmuje: konstruktory i destruktory inicjujące, konstruktor kopiujący oraz tzw. funkcje operatorowe. Konstruktor jest funkcją składową o takiej samej nazwie, jak nazwa klasy. Nazwą destruktora jest nazwa klasy, poprzedzona znakiem tyldy (~). Każda klasa zawiera konstruktor i destruktor, nawet gdy nie są one jawnie zadeklarowane. Zadaniem konstruktora jest konstruowanie obiektów swojej klasy; jego wywołanie w programie pociąga za sobą: alokację pamięci dla obiektu; przypisanie wartości do niestatycznych zmiennych składowych; wykonanie pewnych operacji porządkujących (np. konwersji typów). Jeżeli w klasie nie zadeklarowano konstruktora i destruktora, to zostaną one wygenerowane przez kompilator i automatycznie wywołane podczas tworzenia i destrukcji obiektu.

Przykład #include <iostream> using namespace std; class Punkt { public: Punkt(int, int); void ustaw(int, int); private: int x,y; }; Punkt::Punkt(int a, int b) { x = a; y = b; } void Punkt::ustaw( int c, int d) { x = x + c; y = y + d; } int main() { Punkt punkt1(3,4); //konstruktor return 0; }

Własności konstruktorów i destruktorów Konstruktory i destruktory generowane przez kompilator są public. Konstruktory definiowane przez użytkownika również powinny być public, aby istniała możliwość tworzenia obiektów na zewnątrz deklaracji klasy. W pewnych przypadkach szczególnych konstruktory mogą wystąpić po etykiecie protected:, a nawet private:. Konstruktor jest wołany automatycznie, gdy definiuje się obiekt; destruktor gdy obiekt jest niszczony. Z bloku konstruktora i destruktora mogą być wywoływane funkcje składowe ich klasy.

Kiedy wykorzystujemy konstruktor Konstruktor jest wołany wtedy, gdy ma być utworzony obiekt jego klasy. Obiekt taki może być tworzony na wiele sposobów: jako zmienna globalna; jako zmienna lokalna; przez jawne użycie operatora new; jako obiekt tymczasowy; jako zmienna składowa, zagnieżdżona w innej klasie.

Przykład #include <iostream> #include <conio.h> using namespace std; class Status { public: Status() { licznik++; } ~Status() { licznik--;} int odczyt() { return licznik; } private: static licznik; //deklaracja }; int Status::licznik = 0; // Definicja int main() { Status ob1,ob2, ob3; cout <<"Mamy"<< ob1.odczyt() << " obiekty\n"; //mamy 3 obiekty Status *wsk; wsk = new Status; //Alokuj dynamicznie if (!wsk) { cout << "Nieudana alokacja\n"; return 1; } cout << "Mamy "<< ob1.odczyt()<<" obiekty po alokacji\n" ;// mamy 4 obiekty po alokacji // skasuj obiekt delete wsk; cout << "Mamy "<< ob1.odczyt()<<"obiekty po destrukcji\n"; // mamy 3 obiekty po destrukcji getch(); return 0;

Przeciążanie konstruktorów Konstruktory, podobnie jak “zwykłe” funkcje (także funkcje składowe klasy), mogą być przeciążane. Najczęściej ma to na celu tworzenie obiektów inicjowanych zadanymi wartościami zmiennych składowych, lub też obiektów bez podanych wartości inicjalnych. Dzięki temu można zadeklarować więcej niż jeden konstruktor dla danej klasy. Wywołanie konstruktora w deklaracji obiektu pozwala kompilatorowi ustalić, w zależności od liczby i typów podanych argumentów, którą wersję konstruktora należy wywołać.

Przykład #include <iostream> using namespace std; class Punkt { public: Punkt() {} Punkt(int a, int b): x(a), y(b) {} int x,y; }; int main() { Punkt punkt1(3,4); cout << punkt1.x << endl; Punkt punkt2; cout << punkt2.x << endl; return 0; }

Argumenty domyślne Alternatywą dla przeciążania konstruktora jest wyposażenie go w argumenty domyślne, podobnie jak jest to możliwe dla zwykłych funkcji. Argument domyślny jest przyjmowany przez kompilator wtedy, gdy w wywołaniu funkcji nie podano odpowiadającego mu argumentu aktualnego. Wartości domyślne argumentów formalnych w deklaracji (nie w definicji!) zapisujemy w następujący sposób: Jeżeli w deklaracji konstruktora umieszczono nazwy argumentów formalnych, to po nazwie argumentu piszemy znak równości, a po nim odpowiednią wartość, np. Punkt ( int a = 0, int b = 0 ); Jeżeli deklaracja nie zawiera nazw argumentów, a jedynie ich typy, to znak równości i następującą po nim wartość piszemy po identyfikatorze typu, np. Punkt ( int = 0, int = 0 );

Przykład #include <iostream> #include <conio.h> using namespace std; class Punkt { public: int x,y; Punkt(int = 0, int = 0); }; Punkt::Punkt(int a, int b): x(a), y(b) { if (a==0 && b==0) cout << "Obiekt bez inicjowania...\n"; else cout << "Obiekt z inicjowaniem...\n"; } int main() { Punkt punkt1(3,4); cout << punkt1.x << endl; //x=3 Punkt punkt2; cout << punkt2.x << endl; //x=0 getch(); return 0;

Przeciążanie operatorów W języku C++ są duże możliwości, spotykane w nielicznych współczesnych językach programowania. Ma on do dyspozycji mechanizm, który pozwala tworzyć nowe definicje dla istniejących operatorów. Dzięki temu programista może tak zmodyfikować działanie operatora, aby wykonywał on operacje w narzucony przez niego sposób. Jest to szczególnie istotne w programach czysto obiektowych. Np. obiekty wielokrotnie redefiniowanej klasy Punkt możemy uważać za wektory w prostokątnym układzie współrzędnych. W geometrii i fizyce dla takich obiektów są np. określone operacje dodawania i odejmowania. Byłoby wskazane zdefiniować podobne operacje dla deklarowanych klas przez programistę. Wykorzystamy do tego celu następującą ogólną postać definicji tzw. funkcji operatorowej, tj. funkcji, która definiuje pewien operator “@”: typ klasa::operator@(argumenty) { // wykonywane operacje }

Reguły przeciążania operatorów Operator @ jest zawsze przeciążany względem klasy, w której jest zadeklarowana jego funkcja operator@. Zatem w innych kontekstach operator nie traci żadnego ze swych oryginalnych znaczeń, ustalonych w definicji języka, natomiast zyskuje znaczenia dodatkowe. Funkcja definiująca operator musi być albo funkcją składową klasy, albo mieć co najmniej jeden argument będący obiektem lub referencją do obiektu klasy (wyjątkiem są funkcje, które redefiniują znaczenie operatorów new i delete). Ograniczenie to gwarantuje, że wystąpienie operatora z argumentami typów nie będących klasami, jest jednoznaczne z wykorzystaniem jego standardowej, wbudowanej w język definicji. Jego intencją jest rozszerzanie języka, a nie zmiana wbudowanych definicji. Nie mogą być przeciążane operatory “.”, “.*”, “::”, “?:”, “sizeof” oraz symbole “#” i “##”. Nie jest możliwa zmiana priorytetu, reguł łączności, ani liczby argumentów operatora.

Przykład // Operator dodawania + #include <iostream> using namespace std; class Punkt { public: Punkt(): x(0),y(0){} // zapis x(0) oznacza x=0 -- został wzięty z języka Simula Punkt(int a, int b): x(a),y(a) {} //x(a) jw. int fx() { return x; } int fy() { return y; } Punkt operator+(Punkt); private: int x,y; }; Punkt Punkt::operator+(Punkt p) { return Punkt(x + p.x +7, y + p.y); } int main() { Punkt punkt1, punkt2, punkt3; //konstruktor Punkt() punkt1 = Punkt(2,2); punkt2 = Punkt(3,1); punkt3 = punkt1 + punkt2; //przeciążony cout<<"punkt1.x="<< punkt1.fx() << endl; //2 cout << "punkt3.x= " << punkt3.fx() << endl; //12 int i = 10, j; j = i + 15; // znany '+' cout << " j= " << j << endl; return 0;

Przykład Wyniki Nierowne k= 0 int main() { Punkt punkt1, punkt2; // Operator relacyjny == #include <iostream> using namespace std; class Punkt { public: Punkt(): x(0),y(0) {} Punkt(int a, int b): x(a),y(a) {} int fx() { return x; } int fy() { return y; } int operator==(Punkt); private: int x,y; }; int Punkt::operator==(Punkt p) { if( p.fx() == fx() && p.fy() == fy() ) return (-1); else return (0); } int main() { Punkt punkt1, punkt2; punkt1 = Punkt(2,2); punkt2 = Punkt(3,1); if ( punkt1 == punkt2 ) cout <<„ Rowne\n”; else cout <<„Nierowne\n”; int i = 5, j = 6, k; k = i == j; // predefiniowany '==' cout <<„k=„<< k << endl; return 0; } Wyniki Nierowne k= 0

Język C++ Dziedziczenie

Przykład #include <iostream> Using namespace std; class Bazowa { public: void ustawx(int n): x(n) {} void podajx() { cout << x << "\n"; } private: int x,z; }; class Pochodna : public Bazowa { void ustawy(int m) { y = m; } void podajy() { cout << y << "\n"; } int y; int main() { Pochodna ob; ob.ustawx(10); ob.ustawy(20); ob.podajx(); ob.podajy(); cout << sizeof(Bazowa) << endl; //4B (2*int) cout << sizeof(Pochodna) << endl; //6B (2*int+1*int) cout << sizeof ob << endl; //6B return 0; }