• Nie Znaleziono Wyników

Wykład 6

N/A
N/A
Protected

Academic year: 2021

Share "Wykład 6"

Copied!
1
0
0

Pełen tekst

(1)

Wykład 6

1. Obiekty z dynamicznymi polami typu jednowymiarowa tablica elementów typu struktura. Przeciążanie operatorów: << , >>, []

2. Obiekty z dynamicznymi polami typu dwuwymiarowa tablica elementów typu int- przeciążanie operatora << na rzecz dowolnej klasy oraz operatora wywołania funkcji ()

3. Konwersje typów definiowane przez użytkownika - przeciążanie operatora rzutowania operator typ ()

4. Konwersje typów definiowane przez użytkownika - konwersje z użyciem jednoargumentowych konstruktorów

(2)

1. Obiekty z dynamicznymi polami typu jednowymiarowa tablica elementów typu struktura. Przeciążanie operatorów: << , >>, []

Przykład 6.1

Program w przykładzie 6.1 wprowadza i wyświetla współrzędne wierzchołków wielokąta oraz rysuje wierzchołki w postaci znaków ¦ w miejscach o podanych współrzędnych. Wielokąt jest zawarty w klasie figura, o maksymalnej liczbie wierzchołków określonej liczbą max.

Obiekt typu figura powinien zawierać:

 konstruktor zwykły tworzący dynamiczną tablice struktur Figura zawierających współrzędne wierzchołków (x, y); konstruktor kopiujący tworzący dynamiczną tablicę struktur Figura i kopiujący zawartość przekazywanego obiektu oraz destruktor usuwający tę tablicę

 metodę rysuj, wyświetlającą znak ¦ na ekranie w miejscu (x, y), wtedy gdy znajduje się w obrębie ekranu (1<= x <=80, 1 <=y<=25). Dane każdego wierzchołka pobiera z dynamicznej tablicy struktur Figura.

 metodę przesun, zmieniającą współrzędne x o dx i y o dy wybranego elementu - wierzchołka z tablicy Figura

 dwa przeciążone operatory indeksowania: jeden do odczytu i drugi do zapisu wartości x i y wybranego i-tego elementu - wierzchołka z tablicy Figura

 operator przeciążony >> jako funkcję zaprzyjaźnioną, której lewym argumentem jest obiekt klasy istream, a prawym jest referencja do struktury typu wsp, zdefiniowanego jako prywatny typ klasy figura. Wykorzystanie tej definicji poza blokiem deklaracji klasy jest możliwe dzięki następującej deklaracji

figura::wsp.

W przypadku, gdy struktura typu wsp jest deklaracją public, można stosować nazwę wsp bezpośrednio. Operator przeciążony >> jest wykorzystany do zapisu danych do tablicy struktur Figura, umieszczonej w klasie figura.

 operator przeciążony << jako funkcja zaprzyjaźniona, której lewym argumentem jest obiekt klasy ostream, a prawym jest struktura typu wsp, zdefiniowanego jako prywatny typ klasy figura.

Operator przeciążony << jest wykorzystany do odczytu danych z tablicy struktur Figura, umieszczonej w klasie figura.

 metoda koniec do sprawdzenia, czy jest wolne miejsce w tablicy

Należy zabezpieczyć metody przed dostępem do elementów tablicy Figura poza jej ograniczającymi indeksami 0-(max-1) za pomocą metody koniec.

(3)

...

#include "fig4_3.h"

void wprowadz_punkty(figura&);

void wyswietl(const figura);

void main() { do

{figura wielokat(5);

wprowadz_punkty(wielokat); //sposób wprowadzania obojętny dla klasy wielokat.rysuj(); //operacja powierzona klasie

wyswietl(wielokat); // operacja poza obowiązkami klasy } while (getch() != 27);}

void wprowadz_punkty(figura& wielokat) { int ile = wielokat.podaj_wsp();

for (int i = 0; i < ile; i++)

{cout<< "Podaj wspolrzedne x, y dla wielokat["<<i<<"]: ";

cin >> wielokat[i];

clrscr();}}

void wyswietl(const figura wielokat) { int ile = wielokat.podaj_wsp();

for (int i = 0; i < ile ; i++)

cout<< setw(15)<<"Wielokat["<<i<<"] "<<

setw(5)<<wielokat[i]<<endl;}

class figura //plik nagłówkowy fig4_3.h

{ struct wsp {int x, y;};

int max; // maksymalna liczba współrzędnych w tablicy dynamicznej Figura wsp* Figura; //wskaźnik zgodny z tablicą struktur

int koniec(int) const;

public: figura (int = 1);

figura(figura&);

~figura();

void przesun (int, int, int);

void rysuj() const;

int podaj_wsp() const;

wsp operator[](int) const;

wsp& operator[](int);

friend istream& operator>>(istream&, wsp&);

friend ostream& operator<<(ostream&, const wsp);

(4)

#include "fig4_3.h" //plik z definicjami metod fig4_3.h ...

figura::figura (int xx)

{if (coreleft() < xx*sizeof(wsp)) exit(1);

else

{max = xx;

Figura = new wsp [max];}}

figura::figura (figura& p)

{ if (coreleft() < p.max*sizeof(wsp)) exit(1);

else

{ max = p.max;

Figura = new wsp [max];

for (int i = 0; i < max; i++) Figura[i] = p[i]; } }

figura::~figura() { delete [] Figura; } int figura::koniec(int ile) const {return ile >=0 && ile<max; }

void figura::przesun (int dx, int dy, int ile) { if (koniec(ile))

{ Figura[ile].x += dx;

Figura[ile].y += dy; } }

istream& operator>>(istream& a, figura::wsp& b) { a >> b.x >> b.y;

return a;}

ostream& operator<< (ostream& a, const figura::wsp b) { a << b.x << setw(5)<< b.y;

return a;}

figura::wsp figura::operator[](int ile) const {if (koniec(ile))

return Figura[ile];

return Figura[0]; }

figura::wsp& figura::operator[](int ile) {if (koniec(ile))

return Figura[ile];

return Figura[0]; }

(5)

2. Obiekty z dynamicznymi polami typu dwuwymiarowa tablica elementów typu int- przeciążanie operatora << na rzecz dowolnej klasy oraz operatora wywołania funkcji ()

Przykład 6.2

Klasa figura realizuje te same czynności, co klasa figura z przykładu 6.1, lecz jest wykonana w inny sposób:

 tablica Figura jest dynamiczną tablicą o elementach typu int, traktowaną jako tablica dwuwymiarowa o liczbie wierszy max_w oraz liczbie kolumn max_kol.

Pole ile przechowuje liczbę aktualnie wprowadzonych współrzędnych.

Zastosowanie jednowymiarowej tablicy pozwala na elastyczny podział na dwa wymiary, gdzie wiersze reprezentują liczbę wierzchołków wielokąta, natomiast kolumny określają liczbę wspólrzędnych wierzchołków.

 wykonano operator <<, gdzie lewy argument jest obiektem klasy figura, a prawym argument typu int (kolejne współrzędne). Wynikiem działania operatora, wykonanego jako metoda, jest referencja do lewego argumentu, czyli obiektu wywołującego metodę. Operator ten zastosowano do zapisu współrzędnych wierzchołków wielokąta do tablicy Figura.

 zamiast metod dostępu do współrzędnych np. odcieta(int) i rzedna(int) przeciążono operator wywołania funkcji operator()(int, int) jako metodę, zastępujący indeksowanie [][] w tablicy dwuwymiarowej, niemożliwy do przeciążenia w C++ (można przeciążać tylko operator [] dwuargumentowy, gdzie lewym argumentem jest obiekt, a prawym indeks - tabela, wykład 4) Operator wykorzystano do czytania współrzędnych wierzchołków wielokąta, umieszczonych w tablicy Figura.

Należy zabezpieczyć metody przed dostępem do elementów tablicy Figura poza jej ograniczającymi indeksami 0 <= indeks < max_w *max_kol.

(6)

...

#include "fig4_4.h"

void wprowadz_punkty(figura&);

void wyswietl(const figura);

void main() {do

{ figura wielokat(5, 2);

wprowadz_punkty(wielokat);

wielokat.rysuj();

wyswietl(wielokat);

} while (getch() != 27); }

void wprowadz_punkty(figura& wielokat) { int ile_w = wielokat.podaj_wsp_x(), a;

int ile_kol = wielokat.podaj_wsp_y();

for (int i = 0; i < ile_w; i++) for int j = 0; j < ile_kol; j++)

{ cout << "Podaj wielokat[" << i <<",”<< j << "]:= "; cin >> a;

wielokat << a; }}

void wyswietl(const figura wielokat) { int ile_w = wielokat.podaj_wsp_x();

int ile_kol = wielokat.podaj_wsp_y();

for (int i = 0; i < ile_w; i++) {for int j = 0; j < ile_kol; j++)

cout << setw(15) << "Wielokat[" << i << "," << j << "] " <<

setw(5) << wielokat(i, j);

cout<<'\n';}}

class figura

//plik nagłówkowy fig. 4_4.h {int max_w, max_kol, ile;

int* Figura;

int koniec(int, int) const;

public: figura (int = 1, int = 2);

figura(figura&);

~figura();

void przesun (int, int, int);

void rysuj() const;

int podaj_wsp_x() const;

int podaj_wsp_y() const;

int podaj_ile() const;

figura& operator<<(int);

int operator()(int, int) const; } ;

(7)

#include "fig4_4.h" //plik z definicjami metod fig4_4.cpp ...

figura::figura (int xx, int yy)

{ if (coreleft() < xx*yy*sizeof(int)) exit(1);

else { ile = 0;

max_w = xx;

max_kol = yy

Figura = new int [max_w*max_kol]; } } figura::figura(figura& p)

{if (coreleft() < p.max_w*max_kol*sizeof(int)) exit(1);

else

{ ile = 0;

max_w = p.max_w;

max_kol = p.max_kol;

Figura = new int max_w*max_kol];

for (int i = 0; i < max_w; i++) for (int j = 0; j < max_kol; j++)

*this << p(i, j); }} // Figura[i*max_kol+j] = p(i, j);

int figura::koniec(int ile_w, int ile_kol) const

{return ile_w >=0 && ile_w<max_w && ile_kol>=0 && ile_kol<max_kol; }

figura& figura::operator<<(int xx) { if (ile < max_w*max_kol) Figura[ile++] = xx;

return (*this); }

int figura::operator()(int ile_w, int ile_kol) const {if (koniec(ile_w, ile_kol))

return Figura[ile_w*max_kol + ile_kol];

return Figura[0]; }

(8)

3. Konwersje typów definiowane przez użytkownika - przeciążanie operatora rzutowania operator typ ()

Dwa rodzaje funkcji, obowiązkowo metod (tabela z wykładu 4) umożliwiają zdefiniowanie konwersji przez użytkownika:

konstruktory jednoargumentowe (niezależnie od rodzaju argumentu) przekształcają typ argumentu do typu klasy, do której należą

operatory rzutu do danego typu typ, który może być klasą lub typem podstawowym: operator typ (). Operatory te nie wymagają podania typu zwracanego wyniku. W wyniku rzutu obiekt danej klasy jest przekształcany do typu typ

Reguły do wyboru konwersji są zbliżone do reguł stosowanych przy wywoływaniu przeciążonych funkcji:

 konwersje definiowane przez użytkownika są używane tylko wtedy, kiedy jest to niezbędne

 w jednym ciągu przekształceń (argumentu funkcji lub operatora) może być użyta tylko jedna konwersja definiowana prze użytkownika

 nie może wystąpić wiele ciągów przekształceń prowadzących do tego samego typu

(9)

Przykład 6.3

Wykonano przeciążony operator konwersji operator int() dla klasy punkt. Ciąg przekształceń musi być jednoznaczny. Gdyby przeciążono operator double(), wtedy w przypadku wyrażeń liczba_c=p1+1.25, liczba_r=p1+1,25 byłoby:

 pierwszy ciąg przekształceń: punkt do int, int do double

 drugi ciąg: punkt do double

#include "punkt4_5.h"

...

void wyswietl(int,char []); // 1-a funkcja prezentująca konwersję punkt do int void wyswietl(double,char []); // 2-a funkcja prezentująca konwersję punkt do int void main()

{ {punkt p1(2,2), p2(1,5);

int liczba_c;

double liczba_r;

liczba_c = p1; // p1 do int, int=int

liczba_c = p2; //p2 do int, int=int

wyswietl(p1, s2); //p1 do int, 1-a wyswietl

wyswietl(p2, s2); //p2 do int, 1-a wyswietl

liczba_c = p1+10; //p1 do int, int+int i int =

int

wyswietl(p2+10, s2); //p2 do int, int+int i do 1-a wyswietl liczba_c = p1 + p2; //p1 do int i p2 do int, int+int, int=int wyswietl(liczba_r = p1, s3); //p1 do int, double=int, 2-a wyswietl liczba_r = p1 + 10; //p1 do int, int+int, double=int liczba_r = p1 + p2; //p1 do int, p2 do int, int+int, double=int liczba_c = p1 + 1.25; //p1 do int, int + double, int=double liczba_r = p1 + 1.25; //p1 do int, int + double, double=int

liczba_r = p1; //p1 do int, double=int

} }

void wyswietl(int w, char napis[]) { cout <<napis << w << ’\n’; getch(); } void wyswietl(double w, char napis[]) { cout <<napis << w << ’\n’; getch(); } class punkt

//plik nagłówkowy punkt4_5.h { .... public:...

operator int();}; //operator konwersji obiektu klasy punkt do typu int,

(10)

punkt::operator int () { return x + y; } // operator rzutowania int()

(11)

4. Konwersje typów definiowane przez użytkownika - konwersje z użyciem jednoargumentowych konstruktorów

Przykład 6.4

Zastosowano konwersję za pomocą konstruktora jednoargumentowego typu int do klasy punkt. Wykonano przeciążony operator+ za pomocą funkcji zaprzyjaźnionej. Ciąg przekształceń musi być jednoznaczny.

...

#include "punkt4_6.h"

void wyswietl(punkt, char[]); // funkcja demonstrująca konwersję za pomocą //konstruktora

void main()

{ punkt p1(2, 2), p2(1, 5);

wyswietl(6, s2); // int do punkt (6,0) za pomocą konstruktora

wyswietl(9.9, s2); //float do int, int do punkt (9,0) za pomocą konstruktora p1 = 7; //int do punkt (7,0) za pomocą konstruktora-

//punkt tymczasowy przypisany do p1 i usunięty z wyw. destruktora p2 = 8.8; //double do int (8), int do punkt (8,0) za pomocą

// konstruktora -punkt tymczasowy przypisany do p1 i usunięty p1 = p2 +6; //6 do punkt za pomocą jednoargumentowego konstruktora oraz

//dodawanie p1=operator+(p2, 6)

p1 = 6 + p2; //6 do punkt za pomocą jednoargumentowego konstruktora oraz //dodawanie p1=operator(6, p2); działanie byłoby odrzucone przez kompilator przy //realizacji operatora za pomocą metody, gdyż nie można wywołać 6.operator+(p2) }

void wyswietl(punkt p, char napis[])

{ cout <<napis<< p.odcieta() << " "<< p.rzedna() << ’\n’; getch();}...

//plik nagłówkowy punkt5_5.h class punkt

{ ...

public: punkt (int=0,int=0);

friend punkt operator +(punkt, punkt);

...};

//plik punkt5_5.cpp z definicjami metod

#include "punkt5_5.h"

...

punkt::punkt(int xx, int yy) { x = xx; y = yy; ile_punktow++; } punkt operator+(punkt p1, punkt p2)

{ return (p1.x + p2.x, p1.y + p2.y); }...

Cytaty

Powiązane dokumenty

[r]

Wykonaj następujące czynności w klasie kolo, zakładając, że znana jest definicja klasy punkt (p.1) 2.1) zdefiniuj konstruktor zwykły bez listy argumentów.. 2.2)

619.. gdy ciąg występujący pod znakiem granicy jest rozbieżny, ale nie jest to rozbieżność do +∞ ani do

Im wartość współczynnika korelacja bardziej różni się od 0 tym siła korelacji większa. Zmienne X, Y są liniowo zależne gdy

Dwuwymiarowa zmienna losowa typu skokowego..

[r]

[r]

W nawiasie jest wyra»enie, które ma warto±¢ 5 i jest interpretowane jako true (dowolna warto±¢ niezerowa jest interpretowana jako logiczne true). instrukcja b¦dzie wi¦c