Politechnika Białostocka Wydział Elektryczny Katedra Elektrotechniki Teoretycznej i Metrologii Instrukcja do pracowni specjalistycznej z przedmiotu Informatyka 2 Kod przedmiotu: ES1C300 016 (studia stacjonarne) Spis treści 1. Opis stanowiska... 3 1.1. Stosowana aparatura... 3 1.2. Oprogramowanie... 3 2. Wiadomości teoretyczne... 3 2.1. Funkcje zaprzyjaźnione z klasą... 3 2.2. Przeładowanie (przeciążanie) operatorów... 6 3. Przebieg ćwiczenia... 12 4. Literatura... 13 5. Zagadnienia na zaliczenie... 14 PROGRAMOWANIE OBIEKTOWE W JĘZYKU C++: FUNKCJE ZAPRZYJAŹNIONE Z KLASĄ, PRZEŁADOWANIE OPERATORÓW 6. Wymagania BHP... 14 Numer ćwiczenia INF27 Autor: dr inż. Jarosław Forenc Białystok 2013 Materiały dydaktyczne przeznaczone dla studentów Wydziału Elektrycznego PB. Wydział Elektryczny, Politechnika Białostocka, 2013 (wersja 1.0) Wszelkie prawa zastrzeżone. Żadna część tej publikacji nie może być kopiowana i odtwarzana w jakiejkolwiek formie i przy użyciu jakichkolwiek środków bez zgody posiadacza praw autorskich. Informatyka 2 2 z 15 Instrukcja INF27
1. Opis stanowiska 1.1. Stosowana aparatura Podczas zajęć wykorzystywany jest komputer klasy PC z systemem operacyjnym Microsoft Windows (XP/Vista/7). 1.2. Oprogramowanie Na komputerach zainstalowane jest środowisko programistyczne Microsoft Visual Studio 2008 Standard Edition lub Microsoft Visual Studio 2008 Express Edition zawierające kompilator Microsoft Visual C++ 2008. 2. Wiadomości teoretyczne 2.1. Funkcje zaprzyjaźnione z klasą Funkcja zaprzyjaźniona z klasą jest to funkcja, która nie będąc składnikiem klasy ma dostęp do wszystkich (także prywatnych) składników klasy. W poniższym programie znajduje się definicja klasy opisującej trójkąt. Klasa zawiera dwie dane składowe (a, h), konstruktor oraz dwie funkcje składowe. Funkcja drukuj() wyświetla na ekranie dane składowe klasy, zaś funkcja pole() oblicza pole trójkąta. Program zawierający definicję klasy opisującej trójkąt. #include <iostream> #include <cmath> using namespace std; class trojkat float a; float h; public: trojkat(float wa, float wh) : a(wa), h(wh) float pole(); void drukuj(); ; void trojkat::drukuj() cout << "<a=" << a << ",h=" << h << ">"; float trojkat::pole() return a * h / 2; int main() float wa, wh, p; cout << "Podstawa: "; cin >> wa; cout << "Wysokosc: "; cin >> wh; cout << "---------------------" << endl; trojkat T1(wa,wh); cout << "Trojkat: "; T1.drukuj(); cout << endl; p = T1.pole(); cout << "Pole: " << p << endl; Funkcja pole() jest funkcją składową klasy. Z tego względu nie są do niej przekazywane żadne argumenty. Funkcja składowa klasy jest zawsze wywoływana na rzecz konkretnego obiektu. p = T1.pole(); Funkcja pole() może być zdefiniowana jako funkcja zaprzyjaźniona z klasą. Kod źródłowy programu po wprowadzeniu odpowiednich zmian przedstawiony jest poniżej. Informatyka 2 3 z 15 Instrukcja INF27 Informatyka 2 4 z 15 Instrukcja INF27
Program zawierający definicję klasy trojkat i funkcję pole() zaprzyjaźnioną z klasą. #include <iostream> #include <cmath> using namespace std; class trojkat float a, h; public: trojkat(float wa, float wh) : a(wa), h(wh) void drukuj(); friend float pole(trojkat tr); ; void trojkat::drukuj() cout << "<a=" << a << ",h=" << h << ">"; float pole(trojkat tr) return tr.a * tr.h / 2; int main() float wa, wh, p; cout << "Podstawa: "; cin >> wa; cout << "Wysokosc: "; cin >> wh; cout << "---------------------" << endl; trojkat T1(wa,wh); cout << "Trojkat: "; T1.drukuj(); cout << endl; p = pole(t1); cout << "Pole: " << p << endl; Ponieważ funkcja pole() nie jest funkcją składową klasy, to nie jest wywoływana na rzecz określonego obiektu. Obiekt ten jest przekazywany do funkcji jako jej argument. Definicja funkcji wygląda następująco: float pole(trojkat tr) return tr.a * tr.h / 2; zaś jej wywołanie ma postać: p = pole(t1); Zaprzyjaźnienie funkcji z klasą następuje poprzez umieszczenie deklaracji przyjaźni w definicji klasy. Deklaracja taka zawiera nagłówek funkcji poprzedzony słowem kluczowym friend i zakończony średnikiem. friend float pole(trojkat tr); Nie ma znaczenia, w którym miejscu w definicji klasy pojawia się deklaracja przyjaźni (sekcja private, protected, public). Ta sama funkcja może przyjaźnić się z więcej niż jedną klasą. 2.2. Przeładowanie (przeciążanie) operatorów Przeładowanie operatora polega na nadaniu mu specjalnego znaczenia w momencie, gdy stoi on obok obiektu jakiejś klasy: obiekta operator obiektb Poniżej znajduje się deklaracja trzech obiektów (A, B, C) klasy NazwaK. Wykonanie operacji dodania obiektów A i B oraz przypisanie otrzymanej sumy obiektowi C wymaga przeładowania operatora +. W przypadku niektórych klas konieczne może być także przeładowanie operatora przypisania (=). NazwaK A, B, C; C = A + B; Informatyka 2 5 z 15 Instrukcja INF27 Informatyka 2 6 z 15 Instrukcja INF27
Operator przeładowuje się poprzez napisanie funkcji przedstawionej na Rys. 1. Funkcja przeładowująca operator może być zdefiniowana jako funkcja składowa klasy lub jako funkcja globalna. Załóżmy, że w celu wykonania operacji na dwóch obiektach pewnej klasy, przeładowywany jest operator @: obiekta @ obiektb Definicja funkcji przeładowującej operator w postaci funkcji składowej klasy będzie miała następującą strukturę: Rys. 1. Struktura funkcji przeładowującej operator Można przeładować praktycznie wszystkie operatory. Nie można wymyślać swoich operatorów ani zmieniać ich priorytetu. W każdej klasie automatycznie tworzone są operatory: - przypisania (=); - pobrania adresu (&); - new, new [], delete i delete [] (tworzenie i usuwanie obiektów). Aby przeładowanie było możliwe, jako co najmniej jeden z argumentów funkcji przeładowującej operator musi wystąpić obiekt klasy zdefiniowanej przez użytkownika. Ten sam operator można przeładować wielokrotnie, ale za każdym razem funkcja operatorowa musi mieć inny typ lub kolejność argumentów. NazwaK A, B, C; C = A + B; C = A + 5; C = 5 + A; W powyższym przykładzie, przeładowanie operatora + wymaga zdefiniowania trzech różnych funkcji. W pierwszym przypadku oba argumenty operatora są obiektami klasy NazwaK. W drugim przypadku po lewej stronie operatora znajduje się obiekt klasy NazwaK, zaś po prawej stronie - wartość standardowego typu int. W ostatniej instrukcji po lewej stronie operatora znajduje się wartość typu int, zaś po prawej stronie - obiekt klasy NazwaK. typ_zwracany NazwaK::operator @ (NazwaK obiektb)... Do funkcji przekazywany jest tylko jeden argument (obiektb), natomiast argument obiekta przekazywany jest przez wskaźnik this (funkcja operatorowa jest wywoływana na rzecz obiektu obiekta). Wynika stąd, że obiekt stojący po lewej stronie operatora musi być obiektem tej klasy. Dopuszczalne jest zatem przeładowanie operatora umożliwiające wykonanie operacji typu: obiekta @ obiektb obiekta @ inny_typ Nie jest natomiast możliwe wykonanie operacji typu: inny_typ @ obiekta W poniższym programie znajduje się definicja klasy trojkat, w której przeładowano operator +. Jako sumę dwóch trójkątów przyjęto trójkąt, którego długość podstawy i wysokość są sumami długości podstaw i wysokości dodawanych trójkątów. Funkcję przeładowującą operator zdefiniowano jako funkcję składową klasy. Informatyka 2 7 z 15 Instrukcja INF27 Informatyka 2 8 z 15 Instrukcja INF27
Przeładowanie operatora + w postaci funkcji składowej klasy. #include <iostream> #include <cmath> using namespace std; class trojkat float a, h; public: trojkat(float wa, float wh) : a(wa), h(wh) trojkat operator +(trojkat T2); void drukuj(); ; void trojkat::drukuj() cout << "<a=" << a << ",h=" << h << ">"; trojkat trojkat::operator +(trojkat T2) trojkat TW(0,0); TW.a = a + T2.a; TW.h = h + T2.h; return TW; int main() trojkat TR1(4,5), TR2(5,3), TR3(0,0); cout << "TR1: "; TR1.drukuj(); cout << endl; cout << "TR2: "; TR2.drukuj(); cout << endl; TR3 = TR1 + TR2; cout << "TR3: "; TR3.drukuj(); cout << endl; Wynik działania programu jest następujący: TR1: <a=4,h=5> TR2: <a=5,h=3> TR3: <a=9,h=8> Jeśli funkcja przeładowująca operator jest definiowana w postaci funkcji globalnej to powinna być zaprzyjaźniona z klasą. Jej struktura jest następująca: typ_zwracany operator @ (NazwaK obiekta, NazwaK obiektb)... Do funkcji przekazywane są dwa argumenty. obiekta jest argumentem stojącym po lewej stronie przeładowywanego operatora, zaś obiektb - argumentem stojącym po jego prawej stronie. Stosując przeładowanie w postaci funkcji zaprzyjaźnionej z klasą można wykonywać operacje typu: obiekta @ obiektb obiekta @ inny_typ inny_typ @ obiekta W przypadku programu zawierającego definicję klasy trojkat zmiana funkcji przeładowującej operator z funkcji składowej klasy na funkcję zaprzyjaźnioną z klasą wymaga zastąpienia deklaracji funkcji w definicji klasy przez deklarację przyjaźni: friend trojkat operator +(trojkat T1, trojkat T2); oraz zmianę samej definicji funkcji: trojkat operator +(trojkat T1, trojkat T2) trojkat TW(0,0); TW.a = T1.a + T2.a; TW.h = T1.h + T2.h; return TW; Informatyka 2 9 z 15 Instrukcja INF27 Informatyka 2 10 z 15 Instrukcja INF27
Jednym z częściej przeładowanych operatorów jest operator wstawiania danych do strumienia, czyli <<. W przypadku klasy trojkat przeładowanie tego operatora zastępuje funkcję drukuj(). Po lewej stronie operatora << występuje referencja do obiektu klasy ostream. W związku z tym funkcja przeładowująca operator może być zdefiniowana tylko jako funkcja zaprzyjaźniona z klasą. cout << "TR1: " << TR1 << endl; cout << "TR2: " << TR2 << endl; TR3 = TR1 + TR2; cout << "TR3: " << TR3 << endl; Program zawierający przeładowanie operatorów + oraz <<. #include <iostream> #include <cmath> using namespace std; class trojkat float a; float h; public: trojkat(float wa, float wh) : a(wa), h(wh) friend trojkat operator +(trojkat T1, trojkat T2); friend ostream & operator <<(ostream &ekran, trojkat T); ; trojkat operator +(trojkat T1, trojkat T2) trojkat TW(0,0); TW.a = T1.a + T2.a; TW.h = T1.h + T2.h; return TW; ostream & operator <<(ostream &ekran, trojkat T) ekran << "<a=" << T.a << ",h=" << T.h << ">"; return ekran; int main() trojkat TR1(4,5), TR2(5,3), TR3(0,0); 3. Przebieg ćwiczenia Na pracowni specjalistycznej należy wykonać zadania wskazane przez prowadzącego zajęcia. W różnych grupach mogą być wykonywane inne zadania. 1. W klasie TComplex (Instrukcja INF26, zadanie nr 2) dokonaj następujących zmian: - zastąp funkcję wyświetlającą liczbę zespoloną przeładowaniem operatora <<; - zastąp funkcję obliczającą i zwracającą sumę liczb zespolonych, funkcją przeładowującą operator +; - zastąp funkcję obliczającą i zwracającą różnicę liczb zespolonych, funkcją przeładowującą operator -; - zastąp funkcję obliczającą i zwracającą iloczyn liczb zespolonych, funkcją przeładowującą operator *; - zastąp funkcję obliczającą i zwracającą iloraz liczb zespolonych, funkcją przeładowującą operator /. 2. Zdefiniuj klasę TCena opisującą cenę produktu. Klasa powinna przechowywać, jako pola prywatne, cenę netto (Netto), stawkę VAT w procentach (VAT). W klasie powinny znaleźć się następujące funkcje: - konstruktor dwuargumentowy - zapisujący cenę netto i stawkę VAT, - konstruktor jednoargumentowy - zapisujący cenę netto i przyjmujący 23% jako stawkę VAT, - konstruktor domniemany - zapisujący wartość 0 jako cenę netto i 23% jako stawkę VAT, Informatyka 2 11 z 15 Instrukcja INF27 Informatyka 2 12 z 15 Instrukcja INF27
- funkcja getbrutto() zwracająca cenę brutto (funkcja składowa klasy, definicja funkcji umieszczona poza definicją klasy), - funkcja wyświetlająca cenę brutto w postaci xx.xx PLN (przeładowanie operatora <<), - funkcja getnetto() zwracająca wartość pola Netto (funkcja składowa klasy, definicja funkcji umieszczona wewnątrz definicji klasy), - funkcja getvat() zwracająca wartość pola VAT (funkcja składowa klasy, definicja funkcji umieszczona wewnątrz definicji klasy), - funkcja setnetto() zapisująca nową wartość pola Netto (funkcja składowa klasy, definicja funkcji umieszczona wewnątrz definicji klasy), - funkcja setvat() zapisująca nową wartość pola VAT (funkcja składowa klasy, definicja funkcji umieszczona wewnątrz definicji klasy), - funkcja Przecena(Procent) zmniejszająca cenę netto o Procent starej ceny netto, np. Przecena(50) zmniejsza cenę o połowę (funkcja składowa klasy, definicja funkcji umieszczona poza definicją klasy). Pokaż w programie zastosowanie wszystkich zdefiniowanych funkcji. 4. Literatura [1] Grębosz J.: Symfonia C++ standard: programowanie w języku C++ orientowane obiektowo. Tom 1 i 2. Wydawnictwo Edition 2000, Kraków, 2008. [2] Stroustrup B.: Programowanie. Teoria i praktyka z wykorzystaniem C++. Wydanie II poprawione. Helion, Gliwice, 2013. [3] Eckel B.: Thinking in C++. Edycja polska. Helion, Gliwice, 2002. [4] Prata S.: Język C++. Szkoła programowania. Wydanie VI. Helion, Gliwice, 2012. [5] Stroustrup B.: Język C++. Kompendium wiedzy. Helion, Gliwice, 2014. [6] Wileczek R.: Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows. Helion, Gliwice, 2009. [7] http://www.cplusplus.com/reference/ - C++ Reference 5. Zagadnienia na zaliczenie 1. Wyjaśnij, co to są i kiedy są stosowane funkcje zaprzyjaźnione z klasą. 2. Wyjaśnij na czym polega przeładowanie operatora w klasie. 3. Przedstaw różnice w definicji funkcji przeładowującej operator, w przypadku, gdy jest ona funkcją składową klasy i funkcją globalną. 6. Wymagania BHP Warunkiem przystąpienia do praktycznej realizacji ćwiczenia jest zapoznanie się z instrukcją BHP i instrukcją przeciw pożarową oraz przestrzeganie zasad w nich zawartych. W trakcie zajęć laboratoryjnych należy przestrzegać następujących zasad. - Sprawdzić, czy urządzenia dostępne na stanowisku laboratoryjnym są w stanie kompletnym, nie wskazującym na fizyczne uszkodzenie. - Jeżeli istnieje taka możliwość, należy dostosować warunki stanowiska do własnych potrzeb, ze względu na ergonomię. Monitor komputera ustawić w sposób zapewniający stałą i wygodną obserwację dla wszystkich członków zespołu. - Sprawdzić prawidłowość połączeń urządzeń. - Załączenie komputera może nastąpić po wyrażeniu zgody przez prowadzącego. - W trakcie pracy z komputerem zabronione jest spożywanie posiłków i picie napojów. - W przypadku zakończenia pracy należy zakończyć sesję przez wydanie polecenia wylogowania. Zamknięcie systemu operacyjnego może się odbywać tylko na wyraźne polecenie prowadzącego. Informatyka 2 13 z 15 Instrukcja INF27 Informatyka 2 14 z 15 Instrukcja INF27
- Zabronione jest dokonywanie jakichkolwiek przełączeń oraz wymiana elementów składowych stanowiska. - Zabroniona jest zmiana konfiguracji komputera, w tym systemu operacyjnego i programów użytkowych, która nie wynika z programu zajęć i nie jest wykonywana w porozumieniu z prowadzącym zajęcia. - W przypadku zaniku napięcia zasilającego należy niezwłocznie wyłączyć wszystkie urządzenia. - Stwierdzone wszelkie braki w wyposażeniu stanowiska oraz nieprawidłowości w funkcjonowaniu sprzętu należy przekazywać prowadzącemu zajęcia. - Zabrania się samodzielnego włączania, manipulowania i korzystania z urządzeń nie należących do danego ćwiczenia. - W przypadku wystąpienia porażenia prądem elektrycznym należy niezwłocznie wyłączyć zasilanie stanowiska. Przed odłączeniem napięcia nie dotykać porażonego. Informatyka 2 15 z 15 Instrukcja INF27