ĆWICZENIE 8/2012
1. Dziedziczenie wielobazowe
Dziedziczenie wielobazowe pozwala na tworzenie klas potomnych, dziedziczących z wielu klas bazowych.
Mając np. dwie, zaimplementowane klasy, można zbudować nową klasę, dziedziczącą jednocześnie właściwości obu tych klas. W konstruktorze klasy pochodnej trzeba przekazać w liście inicjalizacyjnej konieczne argumenty do konstruktorów klas bazowych.
Kolejność aktywowania konstruktorów dla obiektu klasy pochodnej wynika z kolejności występowania nazw klas bazowych w deklaracji tej klasy. Nie jest istotna kolejność ich umieszczenia na liście inicjalizacyjnej konstruktora klasy pochodnej.
Kolejność aktywowania destruktorów jest odwrotna do kolejności stosowanej w przypadku konstruktorów.
//Program 8.1
#include <iostream>
class A{
int a;
public:
A(int aa=1){
a=aa;
cout <<"tworze obiekt klasy A "<< a << endl;}
};
class B{
float b;
public:
B(float bb=0.0){
b=bb;
cout <<"tworze obiekt klasy B "<< b << endl;}
};
class C : public A, public B{
int c;
public:
C(int cc=2) : A (2*cc+1), B(12*cc+8) {
c=cc;
cout <<"tworze obiekt klasy C "<< c << endl;}
};
/*
class D : public B, public C{
int d;
public :
D(int d1, int d2, float d3) : C(d1), B(d3){
d=d2;
cout <<"tworze obiekt klasy D "<< d<< endl;}
};
*/
int main(){
C obC(2);
// D obD(10, 20, 5.0);
system("PAUSE");
return EXIT_SUCCESS;
}
Zadanie do samodzielnego wykonania
1. Uruchomić program 8.1 . Jaka jest kolejność wywoływania konstruktorów?
Uruchomić program 8.1 po odblokowaniu fragmentów komentarzy. Co oznacza ostrzeżenie, które pojawia się po kompilacji?
W klasie D zdefiniować:
- metodę wypisz() wypisującą zawartości wszystkich pól obiektu klasy D. Wszystkie pola składowe klas przodków należy umieścić w sekcjach chronionych, aby metoda wypisz() miała dostęp do pól obiektu.
- metodę suma() obliczającą sumę wartości wszystkich pól obiektu klasy D.
Użyć w programie wszystkich zdefiniowanych funkcji.
Wyświetlić rozmiary obiektów klas A, B, C i D.
//Program 8.2
#include <iostream>
using namespace std;
class A{
int na;
public:
A(int nn=1){
na=nn;
cout <<"tworze obiekt A "<< na << endl;}
};
class B : public A{
float xb;
public:
B(float xx=0.0){
xb=xx;
cout <<"tworze obiekt B "<< xb << endl;}
};
class C : public A{
int nc;
public:
C(int nn=2) : A (2*nn+1) {
nc=nn;
cout <<"tworze obiekt C "<< nc << endl;}
};
class D : public B, public C{
int nd;
public :
D(int n1, int n2, float x) : C(n1), B(x) {
nd=n2;
cout <<"tworze obiekt D "<< nd<< endl;}
};
int main(){
D d(10, 20, 5.0);
system("PAUSE");
return 0;
}
Zadanie do samodzielnego wykonania
2. W klasie D zdefiniować:
- metodę wypisz() wypisującą zawartości wszystkich pól obiektu klasy D. Wszystkie pola składowe klas przodków należy umieścić w sekcjach chronionych, aby metoda wypisz() miała dostęp do pól obiektu.
- metodę suma() obliczającą sumę wartości wszystkich pól obiektu klasy D.
Użyć w programie wszystkich zdefiniowanych funkcji.
Wyświetlić rozmiar obiektu klasy D.
Jaka jest kolejność wywoływania konstruktorów?
Uwaga: pole int a występuje w obiekcie klasy D dwukrotnie - odwołując się do niego należy usunąć niejednoznaczność.
2. Dziedziczenie wirtualne (polimorfizm statyczny)
Klasa bazowa może wystąpić kilkakrotnie w hierarchii dziedziczenia. W obiekcie klasy pochodnej występują wówczas wielokrotnie składniki odziedziczone z tej klasy i odwołanie do nich musi być jednoznaczne poprzez klasę pośredniczącą. Ma to szczególne znaczenie w przypadku pól.
W takim przypadku można użyć mechanizmu dziedziczenia wirtualnego klasy bazowej i wówczas składowe odziedziczone z tej klasy wystąpią w obiekcie klasy pochodnej tylko jeden raz.
Pola klas dziedziczonych wirtualnie są umieszczone na końcu obiektu.
W nagłówku konstruktora klasy pochodnej należy przekazać parametry klasom bazowym i klasom wirtualnym.
Przy tworzeniu obiektu najpierw aktywowane są konstruktory klas dziedziczonych wirtualnie w kolejności z nagłówka deklaracji klasy, potem konstruktory pozostałych klas przodków, następnie konstruktory pól typu obiektowego, a na końcu konstruktor klasy pochodnej.
Jeżeli w hierarchii klas występują jednocześnie wirtualne i niewirtualne wystąpienia tej samej klasy, konstruktor tej klasy jest wywoływany raz dla wszystkich wystąpień wirtualnych oraz raz dla każdego niewirtualnego wystąpienia klasy.
//Program 8.3
#include <iostream>
using namespace std;
class A{
int na;
public:
A(int nn=1){
na=nn;
cout <<"tworze obiekt A "<< na << endl;}
};
class B : public virtual A{
float xb;
public:
B(float xx=0.0){
xb=xx;
cout <<"tworze obiekt B "<< xb << endl;}
};
class C : public virtual A{
int nc;
public:
C(int nn=2) : A (2*nn+1) {
nc=nn;
cout <<"tworze obiekt C "<< nc << endl;}
};
class D : public B, public C{
int nd;
public :
D(int n1, int n2, float x) : C(n1), B(x), A(2*n1+1){
nd=n2;
cout <<"tworze obiekt D "<< nd<< endl;}
};
int main(){
D d(10, 20, 5.0);
system("PAUSE");
return 0;
}
Zadanie do samodzielnego wykonania
3. We wszystkich klasach zdefiniować:
- metodę wypisz() wypisującą zawartości wszystkich pól obiektu klasy. Wszystkie pola składowe klas przodków należy umieścić w sekcjach chronionych, aby metody klasy miały dostęp do pól obiektu.
- metodę suma() obliczającą sumę wartości wszystkich pól obiektu każdej klasy.
Wyświetlić rozmiary obiektów klas A, B, C, D.
//Program 8.4
#include <cstdlib>
#include <iostream>
using namespace std;
class zwierze {
protected:
string nazwa;
int waga;
public:
zwierze() {}
zwierze(string a, int b): nazwa(a), waga(b){}
~zwierze(){}
};
class ladowe: public virtual zwierze {
protected:
int liczba_nog;
public:
ladowe(string a, int b, int c): zwierze(a,b), liczba_nog(c){}
~ladowe(){}
};
class wodne: public virtual zwierze {
protected:
float predkosc_plywania;
public:
wodne(string a, int b, float d): zwierze(a,b), predkosc_plywania(d){}
~wodne(){}
};
class dziobak: public ladowe, public wodne {
public:
dziobak(string a, int b, int c, float d):
zwierze(a,b), ladowe(a,b,c), wodne(a,b,d){}
~dziobak(){}
};
int main(int argc, char *argv[])
{ dziobak d("Dzio", 2, 3);
system("PAUSE");
return EXIT_SUCCESS;
}
Zadanie do samodzielnego wykonania
Rozbudować program 8.4 tak by przedstawiał wyścigi na lądzie i na wodzie miedzy żółwiem i dziobakiem.
2012-05-29
INFORMATYKA II - laboratorium
I rok INFORMATYKA
STUDIA STACJONARNE I STOPNIA
Rok akademicki 2011/2012 semestr letni
4