background image

Podstawy

programowania
obiektowego

Ćwiczenia laboratoryjne nr 2

Temat: Konstruktory, destruktory, funkcje zaprzyjaźnione

Prowadzący:

mgr inż. Dariusz Rataj

Koszalin 2001

background image

Podstawy programowania obiektowego ćw nr 2

Strona 2

Spis treści:

1. Konstruktor przeciążony, destruktor obiektu

2. Hermetyzacja - ukrywanie informacji

1.  Konstruktor przeciążony, destruktor obiektu

Dla każdej klasy mamy możliwość utworzenia kilku konstruktorów. Może to być konstruktor
bezparametrowy i konstruktor z parametrami. Jeżeli klasa nie posiada zdefiniowanego
konstruktora to kompilator automatycznie doda konstruktor bezparametrowy. Możemy
także samodzielnie zdefiniować działanie konstruktora bezparametrowego. Przykład  1
definiuje klasę Plik otwierającą plik dyskowy do zapisu. Zdefiniowany został konstruktor
bezparametrowy - tworzący plik o nazwie wbudowanej (default.txt) oraz konstruktor
z parametrem - nazwą pliku dyskowego.

Deklaracja zmiennej obiektowej

 Plik plik1(

"proba.txt"

);  

// konstruktor z parametrem - nazwa pliku

wywoła konstruktor z parametrem i utworzy plik dyskowy o nazwie proba.txt.

Deklaracja zmiennej obiektowej

 Plik plik2;              

// konstruktor bezparametrowy - plik default.txt

wywoła konstruktor bezparametrowy i utworzy plik dyskowy o nazwie wbudowanej
default.txt.

Kompilator automatycznie decyduje jaki konstruktor ma być wywołany w zależności od typu
parametrów w deklaracji obiektu.
Konstruktory w przykładzie  1 wykonują operację otwarcia pliku dyskowego. W takiej
sytuacji programista ma obowiązek zadbać o to aby plik ten został zamknięty przed
zakończeniem programu. Operację  tą wykonuje destruktor (~Plik). Destruktor jest
wywoływany automatycznie w sytuacji gdy obiekt jest zwalniany (kończy się czas życia
obiektu - w tym przykładzie kończy się program). Dzięki zastosowaniu destruktora
programista nie musi pamiętać (zdarza się zapomnieć:-) o zamknięciu pliku przed
zakończeniem programu. Destruktor powinien również zwalniać pamięć rezerwowaną
dynamicznie w czasie działania programu, zamykać połączenia sieciowe itp.

Przykład 1. Definicja klasy Plik, utworzenie dwóch plików dyskowych

#include <stdio.h>

class

 Plik

{
 

private

:

  FILE* plik;              

// zmienna plikowa

 

Public

:

  Plik();                  

// konstruktor bezparametrowy

  Plik(

char

 *NazwaPliku);  

// konstruktor z parametrem - nazwa pliku

  ~Plik();                 

// destruktor

  

void

 zapisz(

char

 *line); 

// metoda zapisujaca linie tekstu do pliku

};

// konstruktor tworzy plik o nazwie wbudowanej default.txt

Plik::Plik()
{
  

if

 ((plik = fopen(

"default.txt"

"wt"

)) == 

NULL

)

  {
   fprintf(stderr, 

"Nie moge otworzyc pliku!!!.\n"

);

  }
}

background image

Podstawy programowania obiektowego

Strona 3

// konstruktor tworzy plik o nazwie podanej jako parametr

Plik::Plik(

char

 *NazwaPliku)

{
  

if

 ((plik = fopen(NazwaPliku, 

"wt"

)) == 

NULL

)

  {
   fprintf(stderr, 

"Nie moge otworzyc pliku!!!.\n"

);

  }
}

void

 Plik::zapisz(

char

 *text)

{
 fprintf(plik, text);   

// zapis lini do pliku

 fprintf(plik, 

"\n"

);   

// przejscie do nastepnej linii

 printf(

"Zapisano do pliku: %s\n\r"

, text);

}

// destruktor zamyka plik

Plik::~Plik()
{
 

if

 (plik) fclose(plik);

}

void

 main()

{
 Plik plik1(

"proba.txt"

);  

// konstruktor z parametrem - nazwa pliku

 Plik plik2;              

// konstruktor bezparametrowy - plik default.txt

 plik1.zapisz(

"--------- plik  proba.txt ------------"

);    

// zapis do 1 pliku

 plik1.zapisz(

"proba zapisu tekstu"

);

 plik1.zapisz(

"---------- koniec zapisu -------------"

);

 plik2.zapisz(

"--------- plik default.txt ----------"

); 

// zapis do 2 pliku

 plik2.zapisz(

"proba zapisu tekstu"

);

 plik2.zapisz(

"---------- koniec zapisu -------------"

);

}

2.  Hermetyzacja - ukrywanie informacji

Projektant-programista ma możliwość ukrycia najbardziej niepewnych części projektu
i przez to zmniejszenia niebezpieczeństwa ewentualnych przeróbek (zmniejszenia wpływu
na pozostałe moduły projektu). W systemach obiektowych przyjęto formalny podział praw
dostępu do interfejsu (warstwy zewnętrznej):

  obszar publiczny (public) widzialny dla wszystkich innych elementów projektu,

  obszar chroniony (protected) widzialny tylko dla podklas danej klasy (niewidzialny

dla innych klas i funkcji),

  obszar prywatny (private) widzialny dla danej klasy i klas, funkcji

zaprzyjaźnionych.

Możemy dopuścić funkcję do obszaru prywatnego klasy przez deklarację klasy jako funkcję
zaprzyjaźnioną. Funkcja zaprzyjaźniona nie jest funkcją składową klasy. W przykładzie 2
zdefiniowane zostały dwie funkcje zaprzyjaźnione: odejmij i porownaj.

Przykład 2. Definicja klasy zespolona, demonstracja działań na liczbach zespolonych

#include <iostream.h>

// cin, cout

#include <math.h>

// fabs, sqrt

#include <conio.h>

#define TRUE 

1

#define FALSE 

0

// deklaracja klasy (interfejs klasy)

class

 zespolona

{

background image

Podstawy programowania obiektowego ćw nr 2

Strona 4

 

public

:

  zespolona();                       

// konstruktor

  zespolona(

double

 r, 

double

 i = 

0

); 

// konstruktor

  

void

 ustaw(

double

 r, 

double

 i);    

// ustawienie wartosci

  

void

 drukuj();

  

void

 czytaj();

  

double

 modul();

  

double

 rzecz() { 

return

 re; }

  

double

 uroj()  { 

return

 im; }

  zespolona sprzez();
  zespolona dodaj(zespolona z);
  

// funkcje zaprzyjaznione z klasa

  friend zespolona odejmij(zespolona z1, zespolona z2);
  friend 

int

 porownaj(zespolona z1, zespolona z2);

 

// pola prywatne

 

private

:

  

double

 re, im;

};

// definicja metod

zespolona::zespolona()
{

re = 

0

; im = 

0

;

}

zespolona::zespolona(

double

 r, 

double

 i)

{

re = r; im = i;

}

void

 zespolona::ustaw(

double

 r, 

double

 i)

{

re = r; im = i;

}

void

 zespolona::drukuj()

{

cout << 

'('

 << re << 

", "

 << im << 

')'

;

}

void

 zespolona::czytaj()

{

cout << 

"re = "

; cin >> re;

cout << 

"im = "

; cin >> im;

}

double

 zespolona::modul()

{

return

 (sqrt(re*re+im*im));

}

zespolona zespolona::sprzez()
{

return

 zespolona(re, -im);

}

zespolona zespolona::dodaj(zespolona z)
{

return

 zespolona(re+z.re, im+z.im);

}

// funkcje zaprzyjaznione odejmij i porownaj

zespolona odejmij(zespolona z1, zespolona z2)
{

return

 zespolona(z1.re-z2.re, z1.im-z2.im);

}

int

 porownaj(zespolona z1, zespolona z2)

{

if

 ( fabs(z1.re-z2.re) < 

1e-10

 && fabs(z1.im-z2.im) < 

1e-10

 )

return

 TRUE;

else

return

 FALSE;

}

background image

Podstawy programowania obiektowego

Strona 5

int

 main()

{

zespolona z1, z2, z3(

1

), z4(

2

3

);

zespolona z5 = z4; 

// inicjalizacja

clrscr();
cout << 

"z1 = "

; z1.drukuj(); cout << 

"\tz1"

 << endl;

cout << 

"z2 = "

; z2.drukuj(); cout << 

"\tz2"

 << endl;

cout << 

"z3 = "

; z3.drukuj(); cout << 

"\tz3(1)"

 << endl;

cout << 

"z4 = "

; z4.drukuj(); cout << 

"\tz4(2, 3)"

 << endl;

cout << 

"z5 = "

; z5.drukuj(); cout << 

"\tz5 = z4"

 << endl << endl;

z1.czytaj();
z2.ustaw(

3

, -

4

);

z3 = z1.sprzez();
z4 = z1.dodaj(z2);
z5 = odejmij(z1, z2);
cout << 

"z1 = "

; z1.drukuj(); cout << 

"\tz klawiatury"

 << endl;

cout << 

"z2 = "

; z2.drukuj(); cout << 

"\tustaw(3, -4)"

 << endl;

cout << 

"z3 = "

; z3.drukuj(); cout << 

"\tsprzezona do z1"

 << endl;

cout << 

"z4 = "

; z4.drukuj(); cout << 

"\tz1 + z2"

 << endl;

cout << 

"z5 = "

; z5.drukuj(); cout << 

"\tz1 - z2"

 << endl << endl;

z1 = z2; 

// podstawienie

cout << 

"z1 = "

; z1.drukuj(); cout << 

"\tz1 = z2"

 << endl;

cout << 

"Re(z1) = "

 << z1.rzecz() << endl;

cout << 

"Im(z1) = "

 << z1.uroj() << endl;

cout << 

"|z1|   = "

 << z1.modul() << endl << endl;

if

 ( porownaj(z1, z2) == TRUE )

cout << 

"z1 jest rowne z2"

 << endl;

else

cout << 

"z1 jest rozne od z2"

 << endl;

cout << endl << 

"Nacisnij dowolny klawisz..."

;

getch();

return

 

0

;

}

Zadania do wykonania na zajęciach i w domu:

1.  Zdefiniuj klasę pilka. Klasa powinna zawierać:

  Pole prywatne a typu całkowitego - promień koła.

  Pole prywatne kolor typu całkowitego - kolor koła.

  Konstruktor bezparametrowy inicjujący wartości początkowe pól (wybrać dowolne).

  Konstruktor z parametrami promień i kolor.

  Metodę publiczną powierzchnia - obliczającą pole powierzchni koła.

  Metodę publiczną ustawPromien - zmieniającą promien koła.

  Metodę publiczną ustawKolor - zmieniającą kolor koła.

Zdefiniuj funkcję zaprzyjaźnioną porownaj - porównującą czy dwa koła mają takie same

powierzchnie i kolor.

2.  Zdefiniuj klasę prostokat. Klasa powinna zawierać:

  Pola prywatne a, b typu całkowitego - dlugość boków prostokąta.

  Konstruktor bezparametrowy inicjujący wartości początkowe pól (wybrać dowolne).

  Konstruktor z parametrami długość i wysokość prostokąta.

  Metodę publiczną powierzchnia - obliczającą pole powierzchni prostokąta.

  Metodę publiczną dajDlugosc - zwracającą długość prostakąta.

  Metodę publiczną dajWysokosc - zwracającą wysokość prostakąta.

Zdefiniuj funkcję zaprzyjaźnioną jestKwadrat - porównującą boki prostokąta (czy jest kwadratem).

3.  Zdefiniuj klasę punkt. Klasa powinna zawierać:

  Pola prywatne x, y typu całkowitego - współrzędne punktu.

  Konstruktor bezparametrowy inicjujący wartości początkowe pól (wybrać dowolne).

  Konstruktor z parametrami: współrzędne punktu.

  Metodę publiczną dajX - zwracającą wsp. x.

  Metodę publiczną dajY - zwracającą wsp. y.

Zdefiniuj funkcję zaprzyjaźnioną porównaj - porównującą współrzędne dwóch punktów (czy punkty

się nakładają).