Wykład 8
Dziedziczenie jednobazowe
1. Dziedziczenie metod i operatorów z przedefiniowaniem
2. Dziedziczenie klas z polami dynamicznymi - definicje konstruktorów zwykłych i kopiowania, destruktorów, przeciążenie operatorów przypisania=, dziedziczenie metod bez/z przedefiniowaniem
Zofia Kruczkiewicz Języki i metody programowania, język C 2, Wykład 8
Politechnika Wrocławska 1
1. Dziedziczenie metod i operatorów z przedefiniowaniem (pokrywaniem) Przykład 8.1
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));
} }
Zofia Kruczkiewicz Języki i metody programowania, język C 2, Wykład 8
Politechnika Wrocławska 2
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) { 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; }
Zofia Kruczkiewicz Języki i metody programowania, język C 2, Wykład 8
Politechnika Wrocławska 3
2. Dziedziczenie klas z polami dynamicznymi - definicje konstruktorów zwykłych i kopiowania, destruktorów, przeciążenie operatorów przypisania=, dziedziczenie metod bez/z przedefiniowaniem
Przykład 8.2
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 (wyklad6.doc /przykład 6.2) oraz klasy pochodnej figura_1, która odwzorowuje zakres indeksów tablicy Figura dla:
wierszy z 0 max_w-1 do pocz_w pocz_w+max_w-1
kolumn z 0 max_kol-1 do pocz_kol pocz_kol+max_kol-1.
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.
Zofia Kruczkiewicz Języki i metody programowania, język C 2, Wykład 8
Politechnika Wrocławska 4
#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 2w = 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);
}
/*
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
2. błąd, gdy nie istnieje konwersja konstruktorowa figura_1::figura_1(figura), tworząca z obiektu p typu figura obiekt klasy figura_1
1.
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).
*/
Zofia Kruczkiewicz Języki i metody programowania, język C 2, Wykład 8
Politechnika Wrocławska 5
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ść cout << setw(15) << "Wielokat[" << i << "," << j << "] " <<
setw(5) << wielokat(i, j);
cout<<'\n';
} }
Zofia Kruczkiewicz Języki i metody programowania, język C 2, Wykład 8
Politechnika Wrocławska 6
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 int podaj_p_k() const;
int podaj_w() const;
int podaj_k() const;
int& operator()(int, int) const; //operator pokryty
figura_1& operator=(const figura_1&); //operator pokryty bez dziedziczenia };
Zofia Kruczkiewicz Języki i metody programowania, język C 2, Wykład 8
Politechnika Wrocławska 7
#include "fig5_4.h" //plik fig5_4.cpp z definicjami metod klasy figura
... // metody zaprezentowane w pliku wyklad6.doc, przykład 6.2
void figura::kopia(const figura& p) // metoda do kopiowania pól klasy figura {
if (coreleft() < p.max_wp.max_kol*sizeof(int)) exit(1);
ile = 0;
max_w = p.max_w;
max_kol = p.max_kol;
Figura = new int [max_wmax_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
}
Zofia Kruczkiewicz Języki i metody programowania, język C 2, Wykład 8
Politechnika Wrocławska 8
#include "fign5_4.h" // plik fign5_4.cpp z definicjami metod klasy figura_1 ...
figura_1::figura_1 (int xx, int yy, int w, int k) : figura(xx,yy), 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);
}
Zofia Kruczkiewicz Języki i metody programowania, język C 2, Wykład 8
Politechnika Wrocławska 9