INF2_27.pdf

(119 KB) Pobierz
Politechnika Białostocka
Wydział Elektryczny
Katedra Elektrotechniki Teoretycznej i Metrologii
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
Instrukcja
do pracowni specjalistycznej z przedmiotu
Informatyka 2
Kod przedmiotu:
ES1C300 016
(studia stacjonarne)
PROGRAMOWANIE OBIEKTOWE W JĘZYKU C++:
FUNKCJE ZAPRZYJAŹNIONE Z KLASĄ,
PRZEŁADOWANIE OPERATORÓW
Numer ćwiczenia
INF27
6. Wymagania BHP ........................................................................................... 14
_____________
Materiały dydaktyczne przeznaczone dla studentów Wydziału Elektrycznego PB.
Autor:
dr inż. Jarosław Forenc
Białystok 2015
© Wydział Elektryczny, Politechnika Białostocka, 2015 (wersja 1.3)
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).
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:
p = T1.pole();
cout <<
"Pole:
}
";
T1.drukuj(); cout << endl;
"
<< p << endl;
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;
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:
p = pole(T1);
cout <<
"Pole:
}
";
T1.drukuj(); cout << endl;
"
<< p << endl;
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;
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:
Informatyka 2
5 z 15
Instrukcja INF27
C = A + B;
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ę:
typ_zwracany NazwaK::operator @ (NazwaK obiektB)
{
...
}
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;
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 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.
Informatyka 2
7 z 15
Instrukcja INF27
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
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;
}
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;
Wynik działania programu jest następujący:
return
TW;
TR1:
TR2:
TR3:
Informatyka 2
<a=4,h=5>
<a=5,h=3>
<a=9,h=8>
9 z 15
Instrukcja INF27
}
Informatyka 2
10 z 15
Instrukcja INF27
Zgłoś jeśli naruszono regulamin