• Nie Znaleziono Wyników

Wykład 5 Dziedziczenie jednobazowe

N/A
N/A
Protected

Academic year: 2021

Share "Wykład 5 Dziedziczenie jednobazowe"

Copied!
1
0
0

Pełen tekst

(1)

Wykład 5

Dziedziczenie jednobazowe

1. Podstawowe definicje

2. Konstruktory w klasach dziedziczących

3. Dziedziczenie metod i operatorów bez przedefiniowania 4. Dziedziczenie metod i operatorów z przedefiniowaniem

5.

Dziedziczenie klas z polami dynamicznymi - definicje konstruktorów zwykłych i kopiowania, destruktorów, przeciążenie operatorów przypisania=, dziedziczenie metod bez/z przedefiniowaniem

1.Podstawowe definicje

(2)

Dziedziczenie to jeden z podstawowych paradygmatów programowania obiektowego (wykład 1).

Pozwala na zdefiniowanie klasy pochodnej B na podstawie istniejącej klasy A, zwanej klasą bazową:

class B : public A // lub private A { //definicja nowych metod i pól

// przedefiniowanie istniejących metod

gdzie public - dziedziczenie publiczne; }; private - dziedziczenie prywatne

6. 2. Dostęp do składowych klasy bazowej A

·

w przypadku dziedziczenia typu public: dostęp klasy-następcy B do wszystkich składowych publicznych klasy bazowej A

·

w przypadku dziedziczenia typu private: składowe publiczne z klasy bazowej A stają się składowymi prywatnymi w klasie pochodnej (np. do całkowitej zmiany interfejsu).

·

w obu przypadkach dziedziczenia składowe prywatne nie są udostępniane klasie-następcy B

·

w celu ochrony składowych klasy bazowej A (hermetyzacja) można zastąpić specyfikator dostępu private specyfikatorem protected: takie składowe są publiczne dla klasy-następcy B, natomiast są prywatne dla jej dla użytkownika

·

jeśli metoda klasy A została przedefiniowana w klasie-następcy B, to w ciele metod klasy B można wywołać pierwotną metodę za pomocą operatora ::

np. A::metoda_p();

·

metody dziedziczone z przedefiniowaniem na rzecz obiektu klasy B są wywoływane za pomocą operatora ::

// metoda_p() jest dziedziczona z przedefiniowaniem od klasy A np. B b; b.A::metoda_p();

·

metody dziedziczone bez przedefiniowania można wywołać bezpośrednio w ciele metod klasy- następcy B

np. metoda();

·

metody dziedziczone na rzecz obiektu klasy B są wywoływane tak samo jak metody zdefiniowane w klasie B

np. B b; b.metoda (); //metoda() jest dziedziczona od klasy A 1.3. Wywołanie konstruktorów i destruktorów

Tworzeniu obiektu następcy B towarzyszy wywołanie niejawne jego

konstruktora i automatyczne wywołanie konstruktora z klasy A. W przypadku

(3)

braku listy argumentów w konstruktorze B, wywoływany jest konstruktor bezargumentowy klasy A (jawny lub domniemany). W przypadku zastosowania listy argumentów w klasie pochodnej B, można wybrać rodzaj konstruktora z klasy bazowej A do inicjowania pól dziedziczonych w B:

B(typ_1 a_1, ...typ_n a_n) : A(a_1, a_2);

Podczas usuwania obiektu wywoływany jest najpierw destruktor (jawny lub domniemany) klasy B, a potem destruktor klasy bazowej A (jawny lub domniemany).

1.4. Wywołanie konstruktora kopiującego

·

w przypadku, gdy w klasie B nie ma jawnego konstruktora kopiującego:

wywoływany jest konstruktor kopiujący domniemany, który wywołuje konstruktor kopiujący z A (jawny lub domniemany, inicjujący pola w B odziedziczone od A) i inicjuje pozostałe pola w B

·

w przypadku, gdy w klasie B jest jawny konstruktor kopiujący z listą argumentów: wywołuje on dowolny konstruktor klasy bazowej A, wymieniony w liście (kopiujący lub zwykły) np.:

·

konstruktor kopiujący z klasy A:

B(B&b) : A(b)

(wywołanie konstruktora kopiującego z A, do którego zostanie przekazana część obiektu klasy B odziedziczona od klasy A);

·

konstruktor zwykły z klasy A:

B(B&b) : A(b.skladowa_1(), b.skladowa_2())

(wywołanie zwykłego konstruktora z klasy bazowej A, do którego przekazuje się dane odziedziczone przez obiekt klasy B od klasy A)

·

w przypadku, gdy w klasie B jest jawny konstruktor kopiujący, lecz nie

zastosowano listy argumentów: wywołuje on konstruktor bezargumentowy

klasy A (jawny lub domniemany)

(4)

1.5. Własności

·

nie można zmienić pól zdefiniowanych w klasie bazowej

· można przedefiniować metody w klasie pochodnej

·

metody dziedziczone działają na obiekcie klasy pochodnej B tak, jak gdyby był obiektem klasy bazowej A,

· dziedziczeniu nie podlegają: konstruktory, destruktory, operator = oraz zaprzyjaźnienia

· istnieją standardowe konwersje typu z klasy pochodnej do klasy bazowej dla obiektów, wskaźników i referencji, dostępne poza zakresem klasy

pochodnej w przypadku publicznej klasy bazowej:

klasa_bazowa ® klasa_pochodna klasa_bazowa * ® klasa_pochodna * klasa_bazowa & ® klasa_pochodna &

W wyrażeniu obiekt_klasy_bazowej = obiekt_klasy_pochodnej kopiowane są tylko pola wspólne w obu klasach w wyniku dziedziczenia

np. punkt p1(1, 2), p2, *p3 kolo k1(2, 3, 4), k2, *k3;

p1 = p2 k2 = k1

k3 = &k2

kolo & k4 = k2

// kopiowane są tylko składowe x i y od obiektu klasy kolo p2 = k1

//zmienna wskaźnikowa p3 jest adresem części klasy punkt w obiekcie k1 klasy //kolo

p3 = &k1 p3 = k3

//zmienna referencyjna p4 jest częścią klasy punkt w obiekcie k2 klasy kolo punkt & p4 = k2

Odwrotne przypisania są błędne, lecz możliwe jest rzutowanie wskaźników:

np. k3 = (kolo*) p3

lub zastosowanie konwersji konstruktorowej kolo::kolo(punkt), tworzącej z obiektu p1 typu punkt obiekt klasy kolo

np. k1 = p1

(5)

2. Konstruktory w klasach dziedziczących Przykład 1

Zrealizować klasę kolo do obsługi kół na płaszczyźnie na podstawie klasy punkt, uzupełniając dane o promień. Należy wykonać konstruktory: zwykły i kopiujący, bez stosowania listy argumentów, w obu klasach punkt i kolo.

...

#include "kolo5_1.h"

#include "punkt5_1.h"

...

void wyswietl(kolo&);

void wyswietl(punkt&);

void wyswietl(float);

void wyswietl(int, int);

void main() { clrscr();

{ wyswietl(kolo::liczba_kol(), kolo::info());

wyswietl(punkt::liczba_punktow(), punkt::info());

/*Wywołanie konstruktorów kola i punktu, lecz z powodu braku listy argumentów, wywołany jest domyślnie bezparametrowy konstruktor punktu, stąd w konstruktorze kola występuje przypisanie (2,2) oraz (1,5) do danych x, y dziedziczonych od punktu*/

kolo k1(2, 2, 3), k2(1, 5, 6);

wyswietl(k1); wyswietl(k2);

wyswietl(kolo::liczba_kol(), kolo::info());

wyswietl(punkt::liczba_punktow(), punkt::info());

/*Wywołanie dziedziczonej metody odleglosc z klasy punkt. Obiekt k2 przy przekazywaniu przez listę parametrów metody jest ograniczony do klasy punkt.*/

wyswietl(k1.odleglosc(k2));

/*Kopiowanie obiektu k1 typu kolo za pomocą konstruktora kopiującego kola i zwykłego konstruktora punktu bezparametrowego z powodu braku listy w konstruktorze kola i utworzenie nowego obiektu k3 typu kolo */

kolo k3 = k1;

wyswietl(k3);

}

wyswietl(kolo::liczba_kol(), kolo::info());

wyswietl(punkt::liczba_punktow(), punkt::info());

}

void wyswietl(kolo& k) {punkt pom;

/*Mozna przypisywać następcę do poprzednika lub obiekty z tych samych klas. Ograniczenie obiektu k typu kolo do obiektu pom typu punkt zapobiega rekurencyjnemu wywołaniu funkcji przeciążonej funkcji wyswietl dla kola*/

pom = k;

wyswietl(pom);

cout <<"Promien: " << k.p_promien() << '\n'; getch();}...

(6)

#include "punkt5_1.h" // plik nagłówkowy kolo5_1.h class kolo:public punkt

{ static int ile_kol; //kolo posiada wszystkie pola klasy punkt oraz własne:

float promien; //ile_kol oraz promien public: kolo (float = 0.0, float = 0.0, float = 0.0);

kolo(kolo&);

~kolo();

float pole() const;

static int liczba_kol(); //dziedziczy wszystkie metody oprócz static int info(); //konstruktorów, destruktora

float& p_promien();}; //metoda do czytania i zapisu składowej promien

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

{ static int ile_punktow;

float x,y;

public: punkt (float = 0.0, float = 0.0);

punkt(punkt&);

~punkt();

void przesun (float, float);

float odleglosc(const punkt&) const;

static int liczba_punktow();

static int info();

float& odcieta(); //metoda do czytania i zapisu składowej x float& rzedna();}; //metoda do czytania i zapisu składowej y

#include "kolo5_1.h" //plik za definicjami metod kolo5_1.cpp

#include "punkt5_1.h"

kolo::kolo(float xx, float yy, float rr)

{ odcieta() = xx; //wywołanie metod w trybie do zapisu składowych

rzedna() = yy;

promien = rr;

/*po nadaniu atrybutu protected polom w klasie punkt można bezpośrednio odwołać się do dziedziczonych pól: x = xx; y = yy;*/

cout<<"Konstruktor zwykly kola\n"; ile_kol++; } kolo::kolo(kolo& p)

{ //wywołanie metod w trybie do zapisu składowych - lewa strona operatora = //wywołanie metod w trybie do odczytu składowych - prawa strona operatora = odcieta() = p.odcieta();

rzedna() = p.rzedna();

promien = p.promien;

ile_kol++; }

kolo::~kolo() { ile_kol--;}

(7)

Przykład 2

Zrealizować klasę kolo do obsługi kół na płaszczyźnie na podstawie klasy punkt, uzupełniając dane o promień. Należy wykonać konstruktory: zwykły i kopiujący, z zastosowaniem listy argumentów, w obu klasach punkt i kolo.

...

#include "kolo5_1.h"

#include "punkt5_1.h"

void wyswietl(kolo&);

void wyswietl(punkt&);

void wyswietl(float);

void wyswietl(int, int);

void main() { clrscr();

{ wyswietl(kolo::liczba_kol(), kolo::info());

wyswietl(punkt::liczba_punktow(), punkt::info());

kolo k1(2, 2, 3), k2(1, 5, 6);

wyswietl(k1); wyswietl(k2);

wyswietl(kolo::liczba_kol(), kolo::info());

wyswietl(punkt::liczba_punktow(), punkt::info());

wyswietl(k1.odleglosc(k2)); .

/*kopiowanie obiektu k1 typu kolo za pomocą konstruktora kopiującego kola i punktu dzięki zastosowanej liście argumentów z jawnie wywołanym konstruktorem kopiującym punktu; utworzenie obiektu k3 typu kolo */

kolo k3 = k1;

wyswietl(k3);

}

wyswietl(kolo::liczba_kol(), kolo::info());

wyswietl(punkt::liczba_punktow(), punkt::info());

}...

#include "kolo5_1.h"

#include "punkt5_1.h"

kolo::kolo(float xx, float yy, float rr): promien(rr), punkt(xx, yy) { ile_kol++; }

kolo::kolo(kolo& p): punkt(p), promien(p.p_promien()) { ile_kol++; }

kolo::~kolo() { ile_kol--;}

(8)

3. Dziedziczenie metod i operatorów bez przedefiniowania (pokrywania) Przykład 3

W klasie bazowej punkt i klasie pochodnej kolo (przykład 2) wykonać:

a) konstruktory: zwykły i kopiujący za pomocą listy argumentów b) operator == jako funkcje zaprzyjaźniona w klasie punkt c) operator != jako metoda klasy punkt.

Operatory te powinny porównywać pola x i y w dwóch obiektach pochodzących z dowolnej klasy (punkt lub kolo).

W przypadku operatorów z b) i c) argument typu kolo jest poddany naturalnej konwersji do klasy punkt.

Stałe typu int są poddane konwersji konstruktorowej do klasy punkt w przypadku operatora b) zawsze, bo:

operator == (obiekt_klasy_punkt, obiekt_klasy_punkt), a w przypadku operatora c) tylko dla prawych argumentów, gdyż:

obiekt_klasy_punkt.operator != (obiekt_klasy_punkt):

b)wyswietl(6==punkt2,”6==punkt2”); ®

operator== (6, punkt2) oraz

wyswietl(8==kolo2,”8==kolo2”); ®

operator == (8, kolo2) ®

poprawne!

c) wyswietl(6!=punkt2,"6!=punkt2 jest rowne ");® 6.operator != (punkt2)

oraz

wyswietl(8!=kolo2,"8!=kolo2 jest rowne ");® 8.operator != (kolo2); ® błędy!

...

#include "kolo5_2.h"

#include "punkt5_2.h"

void wyswietl(kolo&);

void wyswietl(punkt&);

void wyswietl(float);

void wyswietl(int, char *);

void main()

{ kolo kolo1(2, 2, 3), kolo2(1, 5, 6); punkt punkt1 (2, 3), punkt2(2, 8);

wyswietl(kolo1); wyswietl(kolo2); wyswietl(punkt1); wyswietl(punkt2);

wyswietl(punkt1==punkt2, "\npunkt1==punkt2 jest rowne ");

wyswietl(kolo1==kolo2, "kolo1==kolo2 jest rowne ");

wyswietl(punkt1==kolo2, "punkt1==kolo2 jest rowne ");

wyswietl(6==punkt2, "6==punkt2 jest rowne ");

wyswietl(kolo2==8, "kolo2==8 jest rowne ");

wyswietl(punkt1==2, "punkt1==2 jest rowne ");

wyswietl(punkt1!=punkt2, "punkt1!=punkt2 jest rowne ");

wyswietl(kolo1!=kolo2, "kolo1!=kolo2 jest rowne ");

wyswietl(punkt1!=kolo2, "punkt1!=kolo2 jest rowne ");

// wyswietl(6!=punkt2, "6!=punkt2 jest rowne ");

// wyswietl(8!=kolo2," 8!=kolo2 jest rowne ");

wyswietl(punkt1!=2,"punkt1!=2 jest rowne ");}

(9)

class punkt // plik nagłówkowy punkt5_2.h { static int ile_punktow;

float x,y;

public: punkt (float = 0.0,float = 0.0);

punkt(punkt&);

~punkt();

void przesun (float, float);

float odleglosc(punkt&) const;

static int liczba_punktow();

static int info();

float& odcieta();

float& rzedna();

int operator!=(const punkt&);

friend int operator==(const punkt&, const punkt&);

};

#include "punkt5_2.h" //plik nagłówkowy kolo5_2.h class kolo:public punkt

{ static int ile_kol; //kolo posiada wszystkie pola klasy punkt oraz własne:

float promien; //ile_kol oraz promien public: kolo (float=0.0,float=0.0,float=0.0);

kolo(kolo&);

~kolo();

static int liczba_kol(); //dziedziczy wszystkie metody oprócz static int info(); //konstruktorów, destruktora oraz funkcji float& p_promien(); //zaprzyjaźnionej operator==

};

#include "punkt5_2.h" //plik punkt5_2.cpp z definicjami metod klasy punkt punkt::punkt(float xx, float yy) : x(xx),y(yy) { ile_punktow++; } punkt::punkt(punkt& p) : x(p.odcieta()), y(p.rzedna()) { ile_punktow++; }

float& punkt::odcieta() { return x;}

int punkt::operator!=(const punkt& p) { return !(*this==p); }

int operator ==(const punkt &p1, const punkt &p2)

{ return p1.x==p2.x && p1.y==p2.y;} //...

#include "kolo5_2.h" // plik kolo5_2.cpp z definicjami metod klasy kolo

#include "punkt5_2.h"

kolo::kolo(float xx, float yy, float rr): promien(rr), punkt(xx, yy) { ile_kol++; } kolo::kolo(kolo& p) : punkt(p), promien(p.p_promien()) { ile_kol++; } //...

4. Dziedziczenie metod i operatorów z przedefiniowaniem (pokrywaniem)

(10)

Przykład 4

Należy wykonać w klasach: bazowej punkt i pochodnej kolo operatory przedrostkowe i przyrostkowe: operator++ oraz operator--, dokonując przedefiniowania.

Metody te powinny zwiększać lub zmniejszać pola x i y w klasie punkt i dodatkowo pole promien w klasie kolo.

W definicji operatorów w klasie kolo wykorzystać metody-operatory dziedziczone z klasy punkt, np.

punkt::operator++();

w definicji operatora ++

w klasie kolo.

...

#include "kolo5_3.h"

#include "punkt5_3.h"

void wyswietl(kolo&, char *napis);

void wyswietl(punkt&, char *napis);

void wyswietl(float);

void main() { clrscr();

{ kolo kolo1(2, 2, 3), kolo2(1, 5, 6);

punkt punkt1 (2, 3), punkt2(2, 8);

wyswietl(kolo1, "kolo1: "); wyswietl(kolo2, "kolo2: ");

wyswietl(punkt1, "punkt1: "); wyswietl(punkt2, "punkt2: ");

wyswietl(++kolo1, "++kolo1: "); wyswietl(++kolo2, "++kolo2: ");

wyswietl(++punkt1, "++punkt1: "); wyswietl(++punkt2, "++punkt2: ");

wyswietl(--kolo1, "--kolo1: "); wyswietl(--kolo2, "--kolo2: ");

wyswietl(--punkt1, "--punkt1: "); wyswietl(--punkt2, "--punkt2: ");

wyswietl(kolo1--, "kolo1--: "); wyswietl(kolo2--, "kolo2--: ");

wyswietl(punkt1--, "punkt1--: "); wyswietl(punkt2--, "punkt2--: ");

wyswietl(kolo1++, "kolo1++: "); wyswietl(kolo2++, "kolo2++: ");

wyswietl(punkt1++, "punkt1++: "); wyswietl(punkt2++, "punkt2++: ");

wyswietl(kolo1.odleglosc(kolo2));

float a = (kolo1--).odleglosc((kolo2++));

wyswietl(a);

wyswietl(kolo1.odleglosc(kolo2));

}}

(11)

class punkt //plik nagłówkowy punkt5_3.h klasy punkt { float x,y;

public: punkt (float = 0.0, float = 0.0);

punkt(punkt&);

~punkt();

punkt& operator++();

punkt& operator--();

punkt& operator++(int); //fikcyjny parametr dla przyrostkowego ++

punkt& operator--(int); // podobnie jak wyżej dla -- float odleglosc(punkt&) const;

static int info();

float& odcieta();

float& rzedna();};

#include "punkt5_3.h" //plik nagłówkowy kolo5_3.h klasy kolo class kolo : public punkt

{ float promien;

public: kolo (float = 0.0, float = 0.0,float = 0.0);

kolo(kolo&);

~kolo();

kolo& operator ++(); //pokrywanie metod operatorowych kolo& operator --();

kolo& operator ++(int); //fikcyjny operator dla przyrostkowego ++

kolo& operator --(int); //podobnie jak wyżej dla -- static int info();

float& p_promien();};

#include "punkt5_3.h" //plik punkt5_3.cpp z definicjami metod klasy punkt ...

punkt& punkt::operator++() { x += 1; y += 1; return *this; } punkt& punkt::operator++(int a) { x += 1; y += 1; return *this; }

#include "kolo5_3.h" //plik kolo5_3.cpp z definicjami metod klasy kolo

#include "punkt5_3.h"

...

kolo& kolo::operator ++()

{ punkt::operator++(); //wywołanie dziedziczonej metody

promien+=1;

return *this; }

kolo& kolo::operator ++(int)

{ punkt::operator++(3); //wywołanie dziedziczonej metody promien+=1;

return *this; }

5. Dziedziczenie klas z polami dynamicznymi - definicje konstruktorów

(12)

przypisania=, dziedziczenie metod bez/z przedefiniowaniem Przykład 5

Przykład prezentuje dziedziczenie metod i operatorów klas zawierających pole typu dynamiczna dwuwymiarowa tablica elementów typu int. Dotyczy on klasy bazowej figura (wykład4.doc/przykład 4) oraz klasy pochodnej figura_1, która odwzorowuje zakres indeksów tablicy Figura dla:

·

wierszy z 0 ¸ max_w do pocz_w ¸ pocz_w+max_w

·

kolumn z 0 ¸ max_kol do pocz_kol ¸ pocz_kol+max_kol.

Konstruktory klasy figura_1 należy zdefiniować za pomocą listy argumentów. Definiowanie destruktora w klasie figura_1 nie jest konieczne, gdyż pole dynamiczne Figura będzie zwolnione przez destruktor jawny klasy bazowej figura wywołany z destruktora domniemanego klasy pochodnej figura_1.

Klasę figura należy zmodyfikować następująco:

* zadeklarować składowe prywatne jako składowe protected

* zdefiniować operator= umożliwiający tworzenie kopii danych w obiekcie po lewej stronie operatora. Należy pamiętać, że domniemany operator przypisania kopiuje tylko zawartość obiektu, czyli w przypadku pól dynamicznych skopiuje jedynie ich adresy. Wtedy po przypisaniu dwa obiekty korzystają z tych samych pól dynamicznych. Pola dynamiczne obiektu lewego pozostaną w pamięci i będą niedostępne

W klasie figura_1 należy wprowadzić lub zmienić, korzystając z dziedziczenia:

* operator()(int, int), służący do indeksowania dwuwymiarowej tablicy Figura w odwzorowanym zakresie indeksów wierszy i kolumn,

* w metodzie przesun uwzględnić nowy zakres indeksów

·

oraz zadeklarować i zdefiniować operator=, pełniący podobną rolę do operatora = w klasie figura, gdyż operatory przypisania nie są dziedziczone.

Uwagi do programu:

1.konwersja obiektu wielokat do klasy bazowej figura i wywołanie operatora przeciążonego= z klasy figura, który kopiuje pole dynamiczne Figura;

domniemany operator= skopiowałby tylko część obiektu wielokat (część typu figura) do obiektu p; wówczas p i wielokat posiadałyby adres tej samej tablicy dynamicznej bez dostępu do tablicy obiektu p

2. błąd, gdy nie istnieje konwersja konstruktorowa figura_1::figura_1(figura), tworząca z obiektu p typu figura obiekt klasy figura_1

3.wywołanie operatora = z klasy figura_1, który kopiuje pole dynamiczne Figura;

domniemany operator = spełniłby rolę podobną jak w klasie figura (uwaga 1).

(13)

#include "fig5_4.h"

#include "fign5_4.h"

void wprowadz_punkty(figura_1&); //przekazanie przez referencje-zapis void wyswietl(const figura_1); //przekazanie przez wartość- odczyt void main()

{do

{ figura_1 wielokat(5,2,10,15), w(0,0,0) ; //...

figura p(5, 2);

p = wielokat; //uwaga 1

//wielokat = p;

//uwaga 2

w = wielokat; //uwaga 3

cout<<"Nalezy wprowadzic wspolrzedne (x,y) roznych punktow\n";

//...

wprowadz_punkty(wielokat);

//...

wielokat.rysuj();

//...

wyswietl(wielokat);

//...

cout<<" Jesli koniec, nacisnil ESC, dalej - dowolny klawisz\n";

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

void wprowadz_punkty(figura_1& wielokat) {

int i = wielokat.podaj_p_w();

int jj = wielokat.podaj_p_k();

int ile_w = wielokat.podaj_w(), a;

int ile_kol = wielokat.podaj_k();

for (; i < ile_w; i++) //i już przypisane for (int j = jj; j < ile_kol; j++)

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

wielokat << a; }}

void wyswietl(const figura_1 wielokat) {

int i = wielokat.podaj_p_w();

int jj = wielokat.podaj_p_k();

int ile_w = wielokat.podaj_w();

int ile_kol = wielokat.podaj_k(); //...

for (; i < ile_w; i++) //i już przypisane { for(int j = jj; j < ile_kol; j++)

//referencyjny operator() na kopii obiektu przekazanego przez wartość

(14)

cout<<'\n';}}

(15)

class figura //plik nagłówkowy fig5_4.h klasy bazowej figura {

protected: int ile;

int max_w;

int max_kol;

int* Figura;

void kopia(const figura&) int koniec(int,int) const;

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

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;

figura& operator=(const figura&);

};

#include "fig5_4.h" //plik nagłówkowy klasy pochodnej figura_1

class figura_1: public figura {

int pocz_w; //indeksy początkowe wierszy i kolumn

int pocz_kol; //czyli dodatkowe składowe

public:

figura_1 (int = 0, int = 0, int = 0, int = 0);

figura_1(figura_1&);

~figura_1(); //nie jest konieczny- nie ma nowych pól dynamicznych void przesun (int, int, int); //metoda pokryta

int podaj_p_w() const; //nowe metody dotępu do nowych pól int podaj_p_k() const;

int podaj_w() const; //nowe metody wyznaczające liczbę wierszy i kolumn int podaj_k() const; //np. pocz_kol+max_kol

int& operator()(int, int) const; //operator pokryty

figura_1& operator=(const figura_1&); //operator pokryty bez dziedziczenia };

(16)

#include "fig5_4.h" //plik fig5_4.cpp z definicjami metod klasy figura

... // metody zaprezentowane w pliku wyklad5.doc, punkt 3 void figura::kopia(const figura& p) // metoda do kopiowania pól klasy figura { if (coreleft() < p.max_w*p.max_kol*sizeof(int)) exit(1);

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::figura(figura& p) { kopia(p); } figura& figura::operator= (const figura& p) { cout<<"operator przypisania figura\n";

if (this != &p) //przypisywane, gdy różne obiekty klasy figura { delete Figura; //usuwa się tablice w obiekcie po lewej stronie kopia(p); } //operatora przypisania i tworzy kopie tablicy

return (*this); } //z obiektu po prawej stronie instrukcji przypisania

#include "fign5_4.h" // plik fign5_4.cpp z definicjami metod klasy figura_1 ...

figura_1::figura_1 (int xx, int w, int k) : figura(xx), pocz_w(w), pocz_kol(k) { } figura_1::figura_1(figura_1&p) : figura(p),

pocz_w(p.pocz_w),pocz_kol(p.pocz_kol) { } void figura_1::przesun (int d, int ile_w, int ile_kol)

{ figura :: przesun(d, ile_w-pocz_w, ile_kol-pocz_kol); } int& figura_1::operator()(int ile_w, int ile_kol) const

{ return figura :: operator() (ile_w-pocz_w, ile_kol-pocz_kol); } figura_1 & figura_1::operator= (const figura_1& p)

{

if (this != &p) //przypisywane, gdy różne obiekty klasy figura_1 { delete Figura; //usuwa się tablice w obiekcie this po lewej stronie

kopia(p); //operatora przypisania i tworzy kopie tablicy z obiektu p } // przekształconego do klasy figura po prawej stronie instrukcji przypisania pocz_w = p.pocz_w;

pocz_kol = p.pocz_kol;

return (*this); }

Cytaty

Powiązane dokumenty

Z bolącą nogą, poruszając się o dwóch kulach rozpoczęło się na nowo jej zesłańcze życie.. Do Polski wraz z rodzina powróciła 4 marca

Wymienić funkcje w pracy snpłeaznej po zwolnieniu z wojska do chwili obecnej% :..... Stan cywilny

48 W kontekście Lutra zob. Oberman, Marcin Luter. Człowiek między Bogiem a diabłem, przeł. także ogólnie nt. Backus, Reformation Readings of the Apocalypse: Geneva, Zurich,

Poza ekranizacjami powieści związanych bezpośrednio ze Stambułem i historii, które opowiadają o samym mieście, jest ono często tłem dla prezentowanych

Na tej płaszczyźnie człowiek nadal jest celem nadrzędnym, ale zostaje „wbudowany” w architektoniczne konstrukty, do tego stopnia, Ŝe jego samego rozwaŜać moŜna jako

Wspólnie podsumujcie, jakie czynności trzeba wykonać, by za pomocą trzech cięć wykonać figurę niemoż- liwą (możesz zacząć od ucznia, któremu udało się rozwiązać to

Definiowanie destruktora w klasie figura_1 nie jest konieczne, gdyż pole dynamiczne Figura będzie zwolnione przez destruktor jawny klasy bazowej figura wywołany z

Figury polegające na modyfikacji zapisu są pomysłem bardzo starym i ma- jącym wiele źródeł. Jednym z nich są dawne chronogramy, czyli pisane frazy, których pewne litery mogły