Podstawy programowania obiektowego, cw3 cpp

background image

Podstawy

programowania
obiektowego

Ćwiczenia laboratoryjne nr 3

zajęcia zaplanowane na 4 godziny

Temat: Operatory przeciążone, funkcje operatorowe

Prowadzący:

mgr inż. Dariusz Rataj

Koszalin 2001

background image

Podstawy programowania obiektowego ćw nr 2

Strona 2

Spis treści:

1. Przeciążanie operatorów

2. Funkcje operatorowe składowe klasy
3. Funkcje operatorowe zaprzyjaźnione

4. Przykłady

1. Przeciążanie operatorów

Przeciążanie operatora oznacza zdefiniowanie nowego działania operatora dla definiowanej
klasy. W języku C++ mamy możliwość przedefiniowania działania (przeciążenia) prawie
wszystkich operatorów. Wyjątkami są operatory:

. .* ?: :: sizeof

Tworząc nową definicję działania operatora nie zmieniamy jego działania dla typów
standardowych, np.: definiując operator + dla nowotworzonej klasy, działanie tego
operatora dla liczb typu int lub float pozostanie niezmienione. Aby zdefiniować działanie
operatora należy utworzyć funkcję operatorową.
W naszym ćwiczeniu zajmiemy się definicjami podstawowych operatorów dwu
i jednoargumentowych. Funkcje operatorowe możemy zdefiniować jako funkcje składowe
klasy lub jako funkcje zaprzyjaźnione klasy (znane z ćwiczenia nr 2).

2. Funkcje operatorowe składowe klasy

- operatory dwuargumentowe

Operator dwuargumentowy, zdefiniowany jako funkcja składowa klasy, po lewej stronie
zawsze ma argument typu definiowanej klasy. W naszym przykładzie będzie to typ
zespolona.
Przykład:

!

Deklaracja w nagłówku klasy

!

Definicja metody

zespolona zespolona::operator + (zespolona z)
{
zespolona z1(re+z.re, im+z.im);
return z1;
}

zasady stosowania:

Typ zwracany
przez operator

Słowo kluczowe
"operator"

symbol
operatora

Prawy argument
operatora
(typ identyfikator)

zespolona operator + (zespolona z);

background image

Podstawy programowania obiektowego

Strona 3

stosujemy wtedy, gdy lewy argument jest tego samego typu co klasa, np. w operatorach

+ , -, *, /, =, = =,

definicja metody operatorowej poza klasą posiada identyfikator klasy: zespolona:: , tak

samo jak każda inna metoda klasy.

- operatory jednoargumentowe

!

Deklaracja w nagłówku klasy

zespolona operator * ();

!

Definicja metody

zespolona zespolona::operator * ()
{

return zespolona(re, -im);

}

3. Funkcje operatorowe zaprzyjaźnione

Tak zdefiniowany operator po prawej i lewej stronie ma argumenty dowolnego typu.

Przykład:

!

Deklaracja w nagłówku klasy

!

Definicja metody

ostream& operator << (ostream& o, zespolona z)
{

return o << '(' << z.re << ")+(j" << z.im << ')';

}

zasady stosowania:

stosujemy wtedy, gdy lewy argument jest innego typu (może być ten sam typ) co klasa,

np. w operatorach << ,>>. Przeważnie prawy argument jest tego samego typu co
definiowana klasa,

deklaracja metody operatorowej w nagłówku klasy posiada słowo kluczowe friend

informujące, że jest to metoda zaprzyjażniona (nie jest metodą składową klasy!). W
definicji metody to słowo nie występuje.

Typ zwracany
przez operator

Słowo kluczowe
"operator"

symbol
operatora

lewy argument
operatora
(typ identyfikator)

prawy argument
operatora
(typ identyfikator)

Słowo kluczowe
"friend" - metoda
zaprzyjaźniona

friend ostream& operator << (ostream& o, zespolona

z);

background image

Podstawy programowania obiektowego ćw nr 2

Strona 4

przeważnie typ zwracany przez metodę operatorową jest taki sam jak typ lewego

argumentu (możemy przyjąć to jako zasadę). W naszym przykładzie typ ostream&
(referencja na ostream).

4. Przykłady

Przykład 1. Definicja klasy osoba. Klasa zawiera trzy pola prywatne: nazwisko, imie, pesel typu

tekstowego (tablica znaków), dwie funkcje operatorowe zaprzyjaźnione: operator wyjścia << i

operator wejścia >>.

#include <iostream.h>

// cin, cout, ostream, istream

class

osoba

{

private

:

char

nazwisko[

30

], imie[

20

], pesel[

12

];

public

:

osoba();

// operator wyjscia drukuje dane na konsoli

friend ostream& operator <<(ostream& out, osoba& o);

// operator wejscia pobiera dane z konsoli

friend istream& operator >>(istream& in, osoba& o);
};

osoba::osoba()
{
nazwisko[

0

] =

0

;

// pierwszy znak tablicy = 0 -> tekst pusty

imie[

0

] =

0

;

pesel[

0

] =

0

;

}

ostream& operator << (ostream &out, osoba& o)

// op.wyjscia

{
out << o.nazwisko <<

" "

;

out << o.imie <<

" "

;

out << o.pesel <<

" "

;

return

out;

}

istream& operator >> (istream &in, osoba& o)

// op.wyjscia

{
in >> o.nazwisko >> o.imie >> o.pesel;

return

in;

}

void

main()

{
osoba o;

// deklaracja obiektu osoba

cout <<

"\n podaj nazwisko, imie i pesel\n"

;

cin >> o;

// wprowadzenie danych do obiektu

cout << o;

// wyprowadzenie danych na ekran

}

background image

Podstawy programowania obiektowego

Strona 5

Przykład 2. Definicja klasy Plik umożliwiającą wyprowadzenie zawartości pliku na ekran. Klasa zawiera

jedno pole prywatne plik typu FILE * (struktura opisująca strumień - plik dyskowy), funkcję

operatorową zaprzyjaźnioną definiującą operator wyjścia << .

#include <stdio.h>

// FILE, fopen, fclose, ...

#include <iostream.h>

// cout, cin, ostream

class

Plik

{

private

:

FILE* plik;

public

:

Plik(

char

*NazwaPliku);

// konstruktor otwiera plik dyskowy

~Plik();

// destruktor zamyka plik dyskowy

// operator wyjscia drukuje plik na konsoli

friend ostream& operator <<(ostream& out, Plik & pl);
};

Plik::Plik(

char

*NazwaPliku)

{

if

((plik = fopen(NazwaPliku,

"rt"

)) ==

NULL

)

{
fprintf(stderr,

"Nie moge otworzyc pliku!!!.\n"

);

}
}

Plik::~Plik()
{

if

(plik) fclose(plik);

}

ostream & operator << (ostream &out, Plik &pl)

// op.wyjscia

{

char

ch;

fseek(pl.plik,

0

, SEEK_SET);

// na poczatek pliku

do

{
ch = fgetc(pl.plik);
out << ch;
}

while

(ch != EOF);

return

out;

}

void

main()

{
Plik p(

"autoexec.bat"

);

cout << p;
}

background image

Podstawy programowania obiektowego ćw nr 2

Strona 6

Przykład 3. Definicja klasy zespolona. Przykład ten jest rozszerzeniem przykładu z ćwiczenia nr 2

o szereg operatorów jedno i dwuargumentowych. Funkcje operatorowe zostały zdefiniowane jako

składowe klasy lub jako funkcje zaprzyjaźnione. Przykład do samodzielnej analizy.

#include <iostream.h>

// cin, cout, istream, ostream

#include <math.h>

// fabs, sqrt

#include <conio.h>

// clrscr, getch

typedef enum BOOL { FALSE =

0

, TRUE };

// deklaracja klasy (interfejs klasy)

class

zespolona

{

private

:

double

re, im;

public

:

zespolona() { re =

0

; im =

0

; }

zespolona(

double

r,

double

i =

0

): re(r), im(i) { }

void

ustaw(

double

r,

double

i) { re = r; im = i; }

// przeciazone operatory

zespolona operator * ();
zespolona operator + (zespolona z);
friend zespolona operator - (zespolona z1, zespolona z2);
zespolona& operator += (zespolona z);
friend ostream& operator << (ostream &os, zespolona z);
friend istream& operator >> (istream &is, zespolona &z);
friend BOOL operator == (zespolona z1, zespolona z2);

};

// definicja klasy (implementacja klasy), tzn. definicje funkcji
// skladowych klasy i funkcji zaprzyjaznionych z klasa

zespolona zespolona::operator * ()
{

return

zespolona(re, -im);

}

zespolona zespolona::operator + (zespolona z)
{

return

zespolona(re+z.re, im+z.im);

}

zespolona operator - (zespolona z1, zespolona z2)
{

return

zespolona(z1.re-z2.re, z1.im-z2.im);

}

zespolona& zespolona::operator += (zespolona z)
{
re += z.re; im += z.im;

return

*this;

}

ostream& operator << (ostream &os, zespolona z)
{

return

os <<

'('

<< z.re <<

", "

<< z.im <<

')'

;

}

istream& operator >> (istream &is, zespolona &z)
{
cout <<

"re = "

; is >> z.re;

cout <<

"im = "

; is >> z.im;

return

is;

}

BOOL operator == (zespolona z1, zespolona z2)

background image

Podstawy programowania obiektowego

Strona 7

{

if

( fabs(z1.re-z2.re) <

1e-10

&& fabs(z1.im-z2.im) <

1e-10

)

return

TRUE;

else

return

FALSE;

}

int

main()

{

zespolona z1, z2, z3(

1

), z4(

2

,

3

);

zespolona z5 = z4;

// inicjalizacja

clrscr();
cout <<

"z1 = "

<< z1 <<

"\tz1"

<< endl;

// operator << (cout, z1);

cout <<

"z2 = "

<< z2 <<

"\tz2"

<< endl;

cout <<

"z3 = "

<< z3 <<

"\tz3(1)"

<< endl;

cout <<

"z4 = "

<< z4 <<

"\tz4(2, 3)"

<< endl;

cout <<

"z5 = "

<< z5 <<

"\tz5 = z4"

<< endl << endl;

cout <<

"Podaj z1:"

<< endl;

cin >> z1;

// operator >> (cin, z1);

z2.ustaw(

3

, -

4

);

z3 = *z1;

// z3 = z1.operator * ();

z4 = z1 + z2;

// z4 = z1.operator + (z2);

z5 = z1 - z2;

// z5 = operator - (z1, z2);

cout <<

"z1 = "

<< z1 <<

"\tz klawiatury"

<< endl;

cout <<

"z2 = "

<< z2 <<

"\tustaw(3, -4)"

<< endl;

cout <<

"z3 = "

<< z3 <<

"\tsprzezona do z1"

<< endl;

cout <<

"z4 = "

<< z4 <<

"\t= z1 + z2"

<< endl;

cout <<

"z5 = "

<< z5 <<

"\t= z1 - z2"

<< endl << endl;

z4 = z1 +

2

;

// nie mozna: z4 = 2 + z1;

cout <<

"z4 = "

<< z4 <<

"\t= z1 + 2"

<< endl;

z4 = z1 -

2

;

// mozna: z4 = 2 - z1;

cout <<

"z4 = "

<< z4 <<

"\t= z1 - 2"

<< endl;

z5 = z1 + z2 +

2

-

1

- *z1 + z1 + z2 -

1.5

;

cout <<

"z5 = "

<< z5;

cout <<

"\t= z1 + z2 + 2 - 1 - *z1 + z1 + z2 - 1.5"

<< endl;

z1 = z2;

// podstawienie

cout <<

"z1 = "

<< z1 <<

"\tz1 = z2"

<< endl;

z1 += z2;

// z1.operator += (z2);

cout <<

"z1 = "

<< z1 <<

"\tz1 += z2"

<< endl;

if

(z1 == z2)

// if ( operator == (z1, z2) )

cout <<

"z1 jest rowne z2"

<< endl;

else

cout <<

"z1 jest rozne od z2"

<< endl;

cout << endl <<

"Nacisnij dowolny klawisz..."

;

getch();

return

0

;

}

background image

Podstawy programowania obiektowego ćw nr 2

Strona 8

Zadania do wykonania na zajęciach i w domu:

1. Utwórz klasę wektor - jednowymiarową tablicę wartości typu float. Klasa powinna zawierać:

pole prywatne p - wskaźnik na początek tablicy wartości typu float,

konstruktor z parametrem typu int - rozmiarem tablicy tworzący dynamicznie tablicę (new) o
odpowiednim rozmiarze,

destruktor zwalniający pamięć zarezerwowaną przez konstruktor,

funkcję operatorową >>, tak aby można było wprowadzać dane z klawiatury do wektora,

funkcję operatorową <<, tak aby można było wyprowadzać dane z wektora na ekran.

2. Utwórz klasę wektor - jednowymiarową tablicę wartości typu int. Klasa powinna zawierać:

pole prywatne tab - wskaźnik na początek tablicy wartości typy int,

konstruktor z parametrem typu int - rozmiarem tablicy tworzący dynamicznie tablicę (new) o

odpowiednim rozmiarze,

destruktor zwalniający pamięć zarezerwowaną przez konstruktor,

funkcję operatorową >>, tak aby można było wprowadzać dane z klawiatury do wektora,

funkcję operatorową <<, tak aby można było wyprowadzać dane z wektora na ekran.

3. Dla przykładu nr 2 (klasa Plik) rozszerzyć możliwości klasy o funkcje:

konstruktor przeciążony tworzący nowy plik dyskowy,

funkcje operatorową >>, tak aby można było wprowadzać dane z klawiatury do nowego pliku

dyskowego,

funkcję operatorową =, tak aby można było przypisać zawartość pliku,

funkcję operatorową +, tak aby można było dodawać zawartości dwóch plików. Wraz z

operatorem = otrzymamy możliwość wykonania działania:

void main()
{
Plik plik1("pl1.txt"), plik2("pl2.txt"), plik1("pl2.txt");
plik1 = plik2 + plik3;
}

4. Dla przykładu nr 2 (klasa Plik) rozszerzyć możliwości klasy o funkcje:

konstruktor przeciążony tworzący nowy plik dyskowy,

funkcje operatorowe <<, tak aby można było wykonać działanie:

void main()
{
float f = 2.34;
int i = 5;
char tekst[] = "Hallo - to tekst";

Plik plik1("pl1.txt");
plik1 << f;

// zapis do pliku wartości typu

float

plik1 << i; // za

pis do pliku wartości typu

int

plik1 << tekst; // zapis do pliku tekstu z tablicy
}

Uwaga!!! Konieczne jest zdefiniowanie trzech oddzielnych operatorów << dla każdego typu danych.

5. Utwórz klasę okrag - obiekt graficzny. Klasa powinna zawierać:

pola prywatne r - promień, x - wsp. x środka, y - wsp. y środka,

konstruktor z parametrami: promien, wsp. x i y środka,

metodę rysuj rysującą okrag w trybie graficznym systemu DOS,

funkcje operatorową ++ przesuwającą okrąg o 1 punkt w prawo,

funkcje operatorową -- przesuwającą okrąg o 1 punkt w lewo.

funkcje operatorową + dodającą dwa okręgi (działanie dodawania można przyjąć dowolne),

funkcje operatorową = umożliwiającą przypisanie,

funkcje operatorową == porównującą dwa okręgi.


Wyszukiwarka

Podobne podstrony:
Podstawy programowania obiektowego cw3 cpp
Podstawy programowania obiektowego, cw2 cpp
Intuicyjne podstawy programowania obiektowego0
Podstawy programowania obiektowego Dariusz Rataj
Programowanie obiektowe, CPP program, 1
wyklad5.cpp, JAVA jest językiem programowania obiektowego
informatyka-programowanie obiektowe, podstawy
PROZE 3 Podstawy języka, cd programowanie obiektowe
Podstawy Programowania 04 Programowanie Obiektowe
piasecki,podstawy programowania, Definicja klasy, tworzenie obiektów
Nowa podstawa programowa WF (1)
1 Podstawy programowania dialogowego
Programowanie obiektowe(ćw) 1
nowa podstawa programowa sp
11-nkb~1, wisisz, wydzial informatyki, studia zaoczne inzynierskie, podstawy programowania, l2
2-eukl~1, wisisz, wydzial informatyki, studia zaoczne inzynierskie, podstawy programowania, l2
Zmiany w podstawie programowej w zakresie edukcji matematycznej, Wczesna edukacja, Materiały do prac
1-algo~1, wisisz, wydzial informatyki, studia zaoczne inzynierskie, podstawy programowania, l2

więcej podobnych podstron