Lab 8 12, Studia - Politechnika Opolska, Semestr 2, Informatyka


Ć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



Wyszukiwarka