Programowanie obiektowe i C++ dla matematyków

Podobne dokumenty
Programowanie obiektowe i C++ dla matematyków

Wstęp do Programowania 2

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

Programowanie obiektowe i C++ dla matematyków

PARADYGMATY PROGRAMOWANIA Wykład 3

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

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

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.

Operator przypisania. Jest czym innym niż konstruktor kopiujący!

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

Wstęp do Programowania 2

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

public: // interfejs private: // implementacja // składowe klasy protected: // póki nie będziemy dziedziczyć, // to pole nas nie interesuje

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

Programowanie Obiektowe i C++

Programowanie obiektowe w C++ Wykład 12

dr inż. Jarosław Forenc

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

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

Programowanie obiektowe - Przykładowe zadania egzaminacyjne (2005/2006)

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

TEMAT : KLASY POLIMORFIZM

Podstawy języka C++ Maciej Trzebiński. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. Praktyki studenckie na LHC IVedycja,2016r.

Dzisiejszy wykład. Klasa string. wersja prosta wersja ze zliczaniem odwołań. Wyjątki Specyfikator volatile Semafory

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

Programowanie obiektowe i C++ dla matematyków

Szablon klasy std::vector

Kurs programowania. Wykład 3. Wojciech Macyna. 22 marca 2019

Wskaźniki. nie są konieczne, ale dają językowi siłę i elastyczność są języki w których nie używa się wskaźników typ wskaźnikowy typ pochodny:

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

Konstruktor kopiujacy

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

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

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

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

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

TEMAT : KLASY DZIEDZICZENIE

Operatory na rzecz typu TString

Programowanie obiektowe i C++ dla matematyków

Język C++ wykład VIII

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

Program 14. #include <iostream> #include <ctime> using namespace std;

C++ Przeładowanie operatorów i wzorce w klasach

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.

Podstawy języka C++ Maciej Trzebiński. Praktyki studenckie na LHC IFJ PAN. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. M. Trzebiński C++ 1/16

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy WSKAŹNIKI KLASOWE

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.

Operacje wejścia/wyjścia (odsłona druga) - pliki

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

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

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

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

Plik klasy. h deklaracje klas

Paradygmaty programowania. Paradygmaty programowania

Programowanie Obiektowo Zorientowane w języku C++ Klasy, pola, metody

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

Programowanie 2. Język C++. Wykład Relacje między klasami, klasy zagnieŝdŝone, klasy lokalne

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

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

Operacje wejścia/wyjścia odsłona pierwsza

dr inż. Jarosław Forenc

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

C-struktury wykład. Dorota Pylak

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

Programowanie, część I

Programowanie Obiektowo Zorientowane w języku c++ Przestrzenie nazw

PARADYGMATY PROGRAMOWANIA Wykład 4

Wstęp do programowania obiektowego. Przekazywanie parametrów do funkcji w C++ Metody i funkcje operatorowe Strumienie: standardowe, plikowe, napisowe

C-struktury wykład. Dorota Pylak

Do czego służą klasy?

Język C++ umożliwia przeciążanie operatora, tzn. zmianę jego znaczenia na potrzeby danej klasy. W tym celu definiujemy funkcję o nazwie:

Projektowanie klas c.d. Projektowanie klas przykład

Wyliczanie wyrażenia obiekty tymczasowe

Programowanie Obiektowew języku C++ Zadania L2

Programowanie w języku C++

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

Programowanie i struktury danych

Spis treści PROGRAMOWANIE OBIEKTOWE W JĘZYKU C++: FUNKCJE ZAPRZYJAŹNIONE Z KLASĄ, PRZEŁADOWANIE OPERATORÓW. Informatyka 2

Wykład 8: klasy cz. 4

1 Pierwsze kroki w C++ cz.3 2 Obsługa plików

Metody Metody, parametry, zwracanie wartości

Program 22. #include <iostream> using namespace std; struct Osoba { string Imie; string Nazwisko; char Plec; int RokUr; };

Jzyk C++ cz 3. Jarosław Gramacki Instytut Informatyki i Elektroniki ( $)*)+' *, - ( ' )*'.' '',*/ *, ','*0) 1 / ) %*+ 2'' 2" ( $%%) )'20 )*0) 1 / )

PROE wykład 3 klasa string, przeciążanie funkcji, operatory. dr inż. Jacek Naruniec

Część 4 życie programu

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

Programowanie i struktury danych

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

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

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

Struktury Struktura polami struct struct struct struct

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

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

Lista dwukierunkowa - przykład implementacji destruktorów

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

Programowanie obiektowe język C++

Przesłanianie nazw, przestrzenie nazw

Programowanie Obiektowew języku C++ Zadania L4

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

Aplikacje w środowisku Java

Transkrypt:

Programowanie obiektowe i C++ dla matematyków Bartosz Szreder szreder (at) mimuw... 10 I 2012 1 Zabronienie kopiowania Czasami nie ma sensu, żeby obiekty pewnego typu były kopiowane z innych obiektów. Sytuacja taka miała miejsce np. w kontekście kolokwium, na którym pojawiło się zadanie dotyczące implementacji zbiorów. Pojedynczy zbiór pamięta wszystkie swoje elementy, a pojedynczy element zbioru pamięta zbiór do którego należy. Jeśli chcielibyśmy teraz skopiować element zbioru, to najpewniej skopiowalibyśmy także wskaźnik do zbioru zawierającego ten element, co jest kłopotliwe z dwóch powodów: 1. musimy poinformować zbiór, że dodaliśmy do niego nowy element, 2. chociaż nawet i to nie ma większego sensu, bo przecież mamy reprezentować zbiory, a nie multizbiory. W zaproponowanym rozwiązaniu wzorcowym przyjmuje się po prostu, że wskaźnik do zbioru będzie NULL w nowym obiekcie (skopiowanym z istniejącego już), ale widać, że to takie trochę brzydkie rozwiązanie. Żeby zabronić kopiowania (nawet przypadkowego), wystarczy umieścić deklarację konstruktora kopiującego i ew. operatora przypisania w części prywatnej danej klasy: 001 class KlasaNiekopiowalna { 002 private: 003 int a; 004 void operator=(const KlasaNiekopiowalna &); 005 KlasaNiekopiowalna(const KlasaNiekopiowalna &); 006 007 public: 008 KlasaNiekopiowalna(int x = 0) : a(x) {} 009 }; 010 011 int main() 012 { 013 KlasaNiekopiowalna a(5); 014 KlasaNiekopiowalna b = a; //błąd: operator= prywatny 015 KlasaNiekopiowalna c(a); //błąd: konstruktor kopiujący prywatny 1

016 017 return 0; 018 } 2 Klasa Napis Tworzymy klasę reprezentującą napis. Będziemy ją sukcesywnie rozbudowywali o różne funkcjonalności. Na początek ustalamy, że napis będzie reprezentowany jako tablica znaków. Kluczowa będzie metoda dodajznak(), która dopisuje jeden symbol na końcu tablicy, potencjalnie zwiększając ją wcześniej. W poniższym kodzie od razu został zaimplementowany zestaw konstruktorów, potrafiących zbudować napis z typu string z biblioteki standardowej. 001 #include <iostream> 002 #include <string> 003 004 using namespace std; 005 006 class Napis { 007 private: 008 char *data; 009 int cnt; //z ilu znaków składa się napis 010 int size; //rozmiar tablicy data 011 012 void init(const char *, int, int); 013 void init(const Napis &); 014 void init(const string &); 015 void destroy(); 016 017 public: 018 Napis(int); 019 Napis(const Napis &); 020 Napis(const string &); 021 022 Napis(); 023 void operator=(const Napis &); 024 void operator=(const string &); 025 026 void dodajznak(char); 027 void wypisz() const; 028 }; 029 030 void Napis::init(const char *str, int new_cnt, int new_size) 031 { 032 data = new char[new_size]; 033 size = new_size; 034 cnt = new_cnt; 2

035 for (int i = 0; i < cnt; ++i) 036 data[i] = str[i]; 037 } 038 039 void Napis::init(const Napis &n) 040 { 041 init(n.data, n.cnt, n.size); 042 } 043 044 void Napis::init(const string &str) 045 { 046 //c_str() to metoda w string zwracająca napis jako const char * 047 init(str.c_str(), str.size(), str.size()); 048 } 049 050 void Napis::destroy() 051 { 052 delete[] data; 053 } 054 055 Napis::Napis(int initial_size = 10) 056 : cnt(0), size(initial_size) 057 { 058 data = new char[size]; 059 } 060 061 Napis::Napis(const Napis &n) 062 { 063 init(n); 064 } 065 066 Napis::Napis(const string &str) 067 { 068 init(str); 069 } 070 071 Napis:: Napis() 072 { 073 destroy(); 074 } 075 076 void Napis::operator=(const Napis &n) 077 { 078 if (this == &n) 079 return; 080 destroy(); 3

081 init(n); 082 } 083 084 void Napis::operator=(const string &s) 085 { 086 destroy(); 087 init(s); 088 } 089 090 void Napis::dodajZnak(char c) 091 { 092 if (cnt == size) { 093 char *temp = data; 094 095 size = 2 * size + 1; 096 data = new char[size]; 097 for (int i = 0; i < cnt; ++i) 098 data[i] = temp[i]; 099 delete[] temp; 100 } 101 data[cnt++] = c; 102 } 103 104 void Napis::wypisz() const 105 { 106 for (int i = 0; i < cnt; ++i) 107 cout << data[i]; 108 } 109 110 int main() 111 { 112 Napis a("metan"); 113 Napis b(a); 114 115 a.dodajznak( \n ); 116 b.dodajznak( o ); 117 b.dodajznak( l ); 118 b.dodajznak( \n ); 119 120 a.wypisz(); 121 b.wypisz(); 122 return 0; 123 } 4

2.1 Rozbudowa Na razie nasza klasa jest wybitnie koślawa i niewygodna w użyciu. Przeniesiemy zatem metodę dodajznak() do przestrzeni prywatnej i dodajmy kilka operatorów dodawania, których przeznaczeniem będzie konkatenacja napisów. Na razie skupiamy się na operatorach jednoargumentowych deklaracje takich operatorów są częścią klasy. 001 #include <iostream> 002 #include <string> 003 004 using namespace std; 005 006 class Napis { 007 private: 008... 009 void dodajznak(char); //to teraz jest prywatne 010... 011 012 public: 013... 014 void operator+=(char); 015 void operator+=(const Napis &); 016 void operator+=(const string &); 017 }; 018 019 void Napis::operator+=(char c) 020 { 021 dodajznak(c); 022 } 023 024 void Napis::operator+=(const Napis &n) 025 { 026 for (int i = 0; i < n.cnt; ++i) 027 dodajznak(n.data[i]); 028 } 029 030 void Napis::operator+=(const string &str) 031 { 032 for (int i = 0; i < str.size(); ++i) 033 dodajznak(str[i]); 034 } 035 036 int main() 037 { 038 Napis a("metan"); 039 Napis b(a); 040 5

041 a += \n ; 042 b += "ol\n"; 043 044 a.wypisz(); 045 b.wypisz(); 046 return 0; 047 } 2.2 Porozumienie o Braterstwie i Przyjaźni Teraz chcielibyśmy dodać jeszcze dwuargumentowe operatory dodawawania, ale pojawia się pewien problem. Operatory dwuargumentowe definiujemy poza klasami (co jest sensowne, bo przy dwuargumentowych ciężko o sensownie określone this), a to oznacza, że nie będziemy mieli dostępu do atrybutów i metod prywatnych ani do char *data, ani do dodajnapis(). Z pomocą nadchodzi określanie przyjaźni pomiędzy pewną klasą a inną klasą albo pewną klasą i określoną funkcją. Zaprzyjaźniona funkcja otrzymuje dostęp do wszystkich metod i pól prywatnych. Analogicznie zaprzyjaźniona klasa otrzymuje pełen dostęp, tzn. z każdej jej metody możemy grzebać w wewnętrznych flakach danej klasy. Przyjaźń określa się słowem kluczowym friend, następującym przed deklaracją klasy albo funkcji, którą chcemy zaprzyjaźnić. Zaprzyjaźnienie definiujemy wewnątrz klasy przykład poniżej. 001 #include <iostream> 002 #include <string> 003 004 using namespace std; 005 006 class Napis { 007 friend Napis operator+(const Napis &, char); 008 friend Napis operator+(const Napis &, const Napis &); 009 010... 011 }; 012 013 Napis operator+(const Napis &a, char c) 014 { 015 Napis temp(a); 016 temp.dodajznak(c); 017 return temp; 018 } 019 020 Napis operator+(const Napis &a, const Napis &b) 021 { 022 Napis temp(a); 023 for (int i = 0; i < b.cnt; ++i) 024 temp.dodajznak(b.data[i]); 025 return temp; 026 } 6

027 028 int main() 029 { 030 Napis a("metan"); 031 Napis b("ol"); 032 Napis c = a + b + \n ; 033 034 c.wypisz(); 035 return 0; 036 } Relacja przyjaźni w C++ jest bardzo restrykcyjna: nie jest symetryczna, nie jest przechodnia, nie jest dziedziczona. Przyjaźń pozwala łatwo omijać ograniczenia w dostępie do klas, więc nie należy z nią przesadzać, bo zgubi się cały sens podziału na interfejs i implementację. Operatory to jedno z miejsc, w którym użycie przyjaźni wzmacnia siłę tego podziału zamiast go osłabiać. Bez takiego specjalnego wyjątku albo nie moglibyśmy zaimplementować operatorów, albo musielibyśmy odsłonić w interfejsie część implementacji, co jest niepożądane. Ćwiczenie Dopisać i przetestować brakujące dwuargumentowe operatory dodawania: Napis operator+(char, const Napis &) Napis operator+(const Napis &, const string &) Napis operator+(const string &, const Napis &) Należy pamiętać, że konkatenacja napisów nie jest operacją przemienną. 7