background image

 

©2006 Jerzy Kluczewski 

 

 

 
 
 
 
 
 
 
 
 
 

PROGRAMOWANIE OBIEKTOWE 

 
 
 

Ćwiczenia podstawowe Cz. II 

 
 
 
 
 
 

 

Przestrzenie nazw 

 

Obiekty 

 

Klasy 

 

Odwołania do składowych obiektu 

 

Właściwości obiektów 

 

PrzeciąŜanie metod 

 

Sposoby przekazywania argumentów 

 

Dynamiczne obiekty 

 

Konstruktory i destruktory 

 

Konstruktor kopiujący 

 

Składowe statyczne 

 

Dziedziczenie i klasy potomne 

 

Dostęp do składowych klasy 

 

Modyfikatory i dziedziczenie 

 

Przesłanianie składowych klasy 

 

Prosta hierarchia klas 

 
 
 
 

 
 
 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

// MojeSortowanie.h 
//--------------------------------------------------------------------------- 
// definicja przestrzeni nazw 
namespace sudoku  

#define   SIZE   10 
 
// STRUKTURA  przechowująca cyfrę i jej częstosc 
typedef struct { 
   int cyfra; 
   int czestosc; 
} TCzestosc; 
 
// TABLICA przechowująca indeksy o największej liczbie wystąpień 
// cyfr w tablicy liczba_cyfr - posortowane rosnąco 
static TCzestosc  Cyferki[SIZE]; 
 
//--------------------------------------------------------------------------- 
// zeruj częstosc cyfr w tablicy cyferki 
void zeruj_czestosc_cyfr(void) 

for (int i=0; i<SIZE; i++) 
   { 
   Cyferki[i].cyfra = i; 
   Cyferki[i].czestosc = 0; 
   } 

 

I.

 

Przestrzenie nazw 

 
Przykładowy program składa się z dwóch plików: MojeSortowanie.h (biblioteka 
obsługująca przestrzeń nazw sudoku) oraz MojeSortowanie.cpp (plik źródłowy 
programu korzystający ze zmiennych i funkcji naleŜących do przestrzeni nazw sudoku
 
W pliku nagłówkowym w przestrzeni nazw sudoku, zdefiniowano następujące 
elementy: 

 

stałą SIZE 

 

strukturę TCzestosc 

 

tablicę statyczną Cyferki[ROZMIAR_TABL] 

 

funkcję zeruj_czestosc_cyfr 

 

funkcję Cyferki_Sortuj 

 
Oto plik nagłówkowy MojeSortowanie.h 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
Plik MojeSortowanie.h. 
 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               3 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

//--------------------------------------------------------------------------- 
// znajdź indeksy na których pozycji jest największa 
// liczba wystąpień cyfr z tablicy Cyferki i posortuj rosnąco 
void Cyferki_Sortuj(void) 

int nr_cyfry, maksimum; 
TCzestosc temp; 
 
// sortuj met. bąbelkową rosnąco 
// TCzestosc temp słuŜy jako zmienna tymczasowa 
for (int i=0; i<SIZE; i++) 
   { 
   for (int j=SIZE-1; j>=i; j--) 
      if (Cyferki[j-1].czestosc > Cyferki[j].czestosc) 
      { 
         temp.cyfra = Cyferki[j-1].cyfra; 
         temp.czestosc = Cyferki[j-1].czestosc; 
         Cyferki[j-1].cyfra = Cyferki[j].cyfra; 
         Cyferki[j-1].czestosc = Cyferki[j].czestosc; 
         Cyferki[j].cyfra = temp.cyfra; 
         Cyferki[j].czestosc = temp.czestosc; 
      }; 
   }; 
}; 
 
}; // koniec przestrzeni nazw 
#endif 

 
Obowiązujący obecnie standard C++ umoŜliwia właśnie tworzenie własnych 
przestrzeni nazw. Aby to wykonać naleŜy skorzystać z następującego wzorca: 
 
 
 
 
 
 
 
Ciąg dalszy pliku MojeSortowanie.h

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
Po takim zdefiniowaniu przestrzeni nazw, moŜna w innym pliku uŜywać jej 
składowych; są dwa sposoby: 

 

pierwszy polega na uŜyciu konstrukcji  

nazwa_przestrzeni::nazwa_składowej 

 

natomiast drugi polega na uŜyciu konstrukcji  

using   nazwa_przestrzeni; 
nazwa_składowej 
 
 

namespace   nazwa_przestrzeni 

// składowe przestrzeni nazw 
}; 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

#include <iostream> 
#include "MojeSortowanie.h" 
 
using namespace std; 
 
int main() 

int cyfra; 
sudoku::zeruj_czestosc_cyfr(); 
 
for (int i=0; i<10; i++) 
      { 
      cout << "Podaj cyfre:     "; 
      cin >> cyfra; 
      sudoku::Cyferki[cyfra].cyfra = cyfra; 
      sudoku::Cyferki[cyfra].czestosc++; 
      } 
 
sudoku::Cyferki_Sortuj(); 
 
cout << "Cyfra:     "; 
for (int i=0; i<SIZE; i++)   cout<<cout.width(2)<< sudoku::Cyferki[i].cyfra; 
cout << endl; 
cout << "Czestosc:  "; 
for (int i=0; i<SIZE; i++) 
      cout << cout.width(2) << sudoku::Cyferki[i].czestosc; 
   cout << endl << endl; 
   system("pause"); 
   return 0; 

 
W drugim przypadku moŜna korzystać ze wszystkich elementów składowych 
zdefiniowanych w danej przestrzeni nazw, tak jakby były one zdefiniowane w 
aktualnym pliku. 
 
Pierwszy sposób zastosowano w pliku MojeSortowanie.cpp
 
Oto plik źródłowy MojeSortowanie.cpp 

 
 
Program główny MojeSortowanie.cpp. 
 
 
 
 
 
 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               5 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

 

Przestrzeń nazw std 

 
Często powstaje pytanie czy uŜywać iostream czy iostream.h ? Współczesne 
kompilatory C++ zawierają zazwyczaj dwie wersje biblioteki obsługującej strumienie 
wejścia-wyjścia iostream: wersję starszą, której historia sięga początków języka C++, 
oraz wersję nowszą, która powstała oficjalnie po standaryzacji języka w 1998 roku. 
 
Teoretycznie pisząc #include  <iostream.h> , korzystamy z wersji starszej, natomiast 
pisząc #include  <iostream> - z wersji nowszej. W praktyce zaleŜy to od ustawień 
kompilatora. W przypadku środowiska Borland C++ Builder , pisząc #include  
<iostream.h>
, domyślnie i tak korzystamy z nowej biblioteki.  
 
Zapis ten ma takie samo znaczenie jak: 
 
#include  <iostream> 
using  namespace  std;
 
 
W nowej wersji biblioteki iostream wszystkie składowe zostały przeniesione do 
przestrzeni nazw std, a zatem aby z nich skorzystać, naleŜy uŜyć powyŜszej dyrektywy 
using albo teŜ nazwę kaŜdej składowej poprzedzić nazwą std oraz podwójnym 
dwukropkiem, na przykład aby odwołać się do standardowego strumienia wyjściowego 
naleŜy uŜyć konstrukcji 
 
std::cout
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

 
 

II.

 

Obiekty 

 
 
Czym są obiekty? Obiektem moŜe być praktycznie wszystko (Rys. 1): dom, samochód, 
osoba, atom, a w programowaniu obiektem jest kaŜdy abstrakcyjny byt, który zapragnie 
utworzyć programista w pamięci, np. macierz liczb całkowitych, albo stan pól jakiej gry 
planszowej. 
 
Obiekt moŜe przechowywać dane, a takŜe moŜna na nim wykonywać róŜne operacje.  
Obiekt moŜe zawierać inne obiekty, tak samo jak wewnątrz samochodu znajdują się 
fotele, kierownice, silnik. 
 

 

Rys. 1 Obiekty 
 
 

Projekt obiektu 

 
W realnym świecie większość obiektów powstaje na podstawie projektu. W praktyce 
programowania takŜe występuje projektowanie obiektów. Najpierw powstaje projekt, a 
potem są powoływane do Ŝycia (moŜna powiedzieć tworzone)  obiekty o budowie  
i zachowaniu takim jakie przewiduje jego projekt. Taki projekt nazywamy klasą
 
W programowaniu obiektowym – obiekty nie mogą istnieć bez swojego projektu, 
natomiast projekt moŜe istnieć bez obiektów.  
 
 
 

Obiekt 1 

Obiekt 2 

Obiekt 3 

Obiekt 4 

Obiekt 5 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               7 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

 
 

III.

 

Klasa 

 
 
Klasa to projekt (wzorzec) obiektów, a obiekt to konkretna realizacja (egzemplarz) 
zdefiniowanej uprzednio klasy (Rys. 2). 
 
Klasa to takŜe typ definiowany przez programistę, dlatego w środowisku Borland C+ 
Builder przyjęto konwencję, Ŝe nazwy klas rozpoczynają się od litery T
 
 

 

Rys. 2 Klasa i jej obiekty 
 
Klasę deklaruje się za pomocą słowa kluczowego class.  
 
Oto wzór deklaracji klasy: 
 
 
 
 
 
 
 
 
 
Uwaga: Nie naleŜy zapominać o średniku znajdującym się po zamykającym nawiasie 
klamrowym. 
 
Słowo public oznacza, Ŝe dostęp do wnętrza klasy jest publiczny, czyli Ŝe do 
elementów klasy moŜna się odwoływać bez ograniczeń. 
 

Obiekt 1 

Obiekt 2 

Obiekt 3 

Obiekt 4 

Klasa (projekt obiektów) – 
opisuje właściwości i sposoby 
zachowania się obiektów 

class   nazwa_klasy 

public: 
// definicja wnętrza klasy 
}; 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

 
 
 

Klasa TPunkt 

 
Oto deklaracja klasy TPunkt będąca projektem obiektów przechowujących dane 
(współrzędne x i y punktów) o połoŜeniu punktów na ekranie. 
 
 
 
 
 
 
 
 
 
Zmienne x, y nazywa się składowymi klasy
 

Pola klasy 

 
Dane przechowywane w klasie (zmienne) nazywamy polami klasy
 

Metody klasy 

 
Kod umieszczany w klasie (funkcje działające na polach) nazywamy metodami klasy
 
Klasa zawiera pola (dane) oraz metody (wykonywane czynności). 
 
Deklaracje klasy (określające strukturę klasy), zazwyczaj umieszcza się w plikach 
nagłówkowych z rozszerzeniem .h, natomiast definicje klasy w plikach .cpp
 

Określenie struktury klasy 

 
 
 
 
 
 
 
 
 
 
 
Plik Punkt.h 

 

Do klasy TPunkt dodano dwie metody, które mają za zadanie pobierać wartości pól 
klasy. Metody te noszą nazwy pobierzX i pobierzY
 

class   TPunkt 

public: 
int  x;  
int  y; 
}; 

class   TPunkt 

public: 
int  x;  
int  y; 
int  pobierzX(); 
int  pobierzY(); 
}; 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               9 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

 
 
PowyŜsza deklaracja klasy TPunkt oznacza: 
 
Definiuję nowy typ danych TPunkt.  
Obiekty tego typu będą zawierały pola o nazwach x i y, oba typu int.  
Obiekty tego typu będą zawierały dwie metody – jedna o nazwie pobierzX, druga 
będzie się nazywała pobierzY, obie będą zwracały wartość typu int
 
Teraz naleŜy zdefiniować, co będą robiły te metody. Definicje metod naleŜy wpisać do 
pliku Punkt.cpp
 
Definicje te muszą mieć następującą postać: 
 
 
 
 
 
 
 
 
Do pliku Punkt.cpp dopisano definicje dwóch metod: pobierzXpobierzY, pierwsza z 
nich odczytuje wartość pola x z obiektu klasy TPunkt, a druga odczytuje wartość pola 
y z obiektu klasy Punkt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Plik Punkt.cpp 
 
Uwaga: Przy tworzeniu pliku głównego programu Punkt.cpp, nie moŜna zapomnieć  
o dołączeniu do niego pliku nagłówkowego zawierającego deklaracje klasy (Punkt.h).  
 
Po utworzeniu plików Punkt.h i Punkt.cpp moŜna juŜ zająć się tworzeniem obiektów 
klasy TPunkt
 
SłuŜy do tego następująca konstrukcja: 
nazwa_klasy    nazwa_obiektu; 
 

typ_zwracany       nazwa_klasy  ::  nazwa_metody() 

// treść metody 
}; 

#include  "Punkt.h" 
#include  <iostream.h> 
 
int TPunkt::pobierzX() 

return x; 

 
int TPunkt::pobierzY() 

return y; 

background image

10 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

#include  "Punkt.h" 
#include  <iostream.h> 
 
int TPunkt::pobierzX() 

return x; 

 
int TPunkt::pobierzY() 

return y; 

 
int main() 

   TPunkt  punkt; 
   punkt.x = 1; 
   punkt.y = 1; 
   cout << "Wartosc pola x z obiektu punkt to "; 
   cout << punkt.x << endl; 
   cout << "Wartosc pola y z obiektu punkt to "; 
   cout << punkt.y << endl; 
   system("pause"); 
   return 0; 

 
 
 
Aby program był w pełni funkcjonalny, naleŜy dopisać funkcję main z odpowiednim 
kodem. 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Program Punkt.cpp. 
 
Po wykonaniu instrukcji TPunkt punkt, w pamięci komputera powstanie obiekt punkt 
klasy TPunkt
 
MoŜna powiedzieć, Ŝe  punkt to zmienna typu obiektowego TPunkt, albo Ŝe punkt 
jest instancją (wystąpieniem) klasy TPunkt. (w skrócie będziemy uŜywali słowa obiekt 
zamiast zmienna typu obiektowego i klasa zamiast typ obiektowy

 
Gdyby w programie napisać: 
TPunkt  punkt1; 
TPunkt  punkt2; 
 
to utworzone zostaną dwa obiekty (dwie instacje) klasy TPunkt
 
Operator „kropka” pozwala na bezpośredni dostęp do pól obiektu punkt. Instrukcja 
punkt.x  = 1 pozwala na przypisanie wartości 1 do pola x w obiekcie punkt

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               11 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

int main() 

   TPunkt  pierwszyPunkt, drugiPunkt; 
   pierwszyPunkt.x = 100; 
   pierwszyPunkt.y = 200; 
   drugiPunkt.x = 300; 
   drugiPunkt.y = 400; 
   cout << "Wartosci pol obiektu pierwszyPunkt:" << endl; 
   cout << "x= "<< pierwszyPunkt.pobierzX() << ", "; 
   cout << "y= "<< pierwszyPunkt.pobierzY() << endl; 
   cout << "Wartosci pol obiektu drugiPunkt:" << endl; 
   cout << "x= "<< drugiPunkt.pobierzX() << ", "; 
   cout << "y= "<< drugiPunkt.pobierzY() << endl; 
   return 0; 

 
 

Odwołania do składowych obiektu 

 
Stosowanie obiektów pozbawione byłoby sensu, gdyby nie moŜna było się odwoływać 
(odczytywać lub zapisywać do pól obiektu) do ich składowych lub teŜ wywoływać ich 
metody.  
 
Do tego celu stosujemy operator 

 (kropka). Na przykład dla zmiennej obiektowej 

punkt do jej pola x naleŜy wpisać wartość 20 – wykonuje się to za pomocą następującej 
instrukcji: 
punkt.x  = 10; 
 
Odczyt wartości pola x ze zmiennej obiektowej punkt – wykonuje się to za pomocą 
następującej instrukcji: 
wartość  =  punkt.x; 
 
Podobnie jest w przypadku metod. Wywołanie metody polega na podaniu nazwy 
zmiennej obiektowej, znaku kropki i nazwy metody n.p. 
 
int wspX  = punkt.pobierzX(); 
 

Wiele obiektów tej samej klasy 

 
W jednym programie moŜe istnieć wiele obiektów tej samej klasy. Program 
Punkt2.cpp demonstruje taką sytuację. Do odczytu zawartości pól obiektu 
wykorzystywane są metody pobierzXpobierzY. Za pomocą kodu programu tworzone 
są dwa obiekty pierwszyPunktdrugiPunkt, przypisywane są róŜne wartości do pól 
obiektów, a za pomocą odpowiednich metod uzyskiwane są wartości tych pól. 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
Program Punkt2.cpp. 

background image

12 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

 

IV.

 

Właściwości obiektu 

 
Za pomocą metod moŜna zmieniać właściwości obiektu. W poprzednim przykładzie 
klasa TPunkt nie posiadała takich moŜliwości. Nic nie stoi na przeszkodzie, aby w 
klasie dopisać metody ustawiające wartości pól x i y. Metody te muszą jednak mieć 
moŜliwość pobierania argumentów (czyli wartości, które będą przesyłały do wnętrza 
obiektu). Metody te tworzą tzw. interfejs klasy, pozwalający na dostęp do obiektów tej 
klasy (Rys. 3). 
 

 

 

 

 
 

 

Rys. 3. Metody jako interfejs dostępu programu do pól obiektu. 
 
 

Argumenty metod 

 
KaŜda metoda, tak jak funkcja w C++, moŜe przyjmować argumenty, czyli dane. 
Argumenty umieszcza się w nawiasach okrągłych, oddzielając je od siebie znakami 
przecinka. Oto schemat takiej konstrukcji: 
 
typ_zwracanego wyniku   

nazwa_metody

(typ_1  argument_1, typ_2  argument_2

…  typ_n  argument_n
 
Przykład interfejsu do obiektu klasy punkt (Rys.4). 
 
 
 
 
 
 
 
Rys. 4. Metody ustawiające wartości pól obiektu klasy TPunkt. 
 

Pole y 

Pole x 

Metody: 
 
pobierzX 
pobierzY
 
 
ustawX 
ustawY 
 

Obiekt punkt 

Program 
główny 

dostęp 

 
void 

ustawX

(int   wspX

 

void 

ustawY

(int   wspY

 

wsp

wsp

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               13 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

 
Projekt zmodyfikowanej klasy TPunkt będzie teraz wyglądał następująco: 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Plik Punkt.h 
 
 
Natomiast definicje metod w programie Punkt3.cpp będą wyglądały następująco: 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Plik Punkt3.cpp 
 
 

class   TPunkt 

public: 
int  x;  
int  y; 
 
int  pobierzX(); 
int  pobierzY(); 
 
void ustawX(int   wspX); 
void ustawY(int   wspY); 
}; 

#include  <iostream> 
#include  "Punkt.h" 
using namespace std; 
int TPunkt::pobierzX() 

return x; 

 
int TPunkt::pobierzY() 

return y; 

 
void TPunkt::ustawX(int  wspX) 

x  =  wspX; 

 
void TPunkt::ustawY(int  wspY) 

y  =  wspY; 

background image

14 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

void TPunkt::ustawX(int  x) 

x  =  x; 

void TPunkt::ustawX(int  x) 

this->x = x; 

 
void TPunkt::ustawY(int  y) 

this->y = y; 

 
 
 

Odwołanie this 

 
Co się stanie, gdy w metodzie danej klasy uŜyjemy argumentu o identycznej nazwie jak 
jedno z pól, (patrz przykład poniŜej) ?  

 
 
 
 
 
 

 
PowyŜsza definicja metody jest formalnie poprawna, lecz jest bez sensu!!! Aby 
odróŜnić w niej nazwę pola x klasy TPunkt od nazwy argumentu x, naleŜy posłuŜyć się 
słowem kluczowym this, które oznacza obiekt bieŜący (jest synonimem obiektu 
bieŜącego). NaleŜy zastosować konstrukcję 
 
this







nazwa_pola

 
Operator 

 jest równoznaczny z operatorem (kropka), dlatego w tym przypadku 

operacja this







x jest traktowana tak samo jak punkt.x. Poprawne uŜycie argumentu x 

w definicji metod ustawXustawY wygląda następująco: 

 
 
 
 
 
 
 
 
 
 
 

 
 

Konstrukcja 

Interpretacja konstrukcji 

int x; 

zmienna x typu int 

this









pole x w aktualnym obiekcie  

punkt.x 

pole x w obiekcie punkt 

 
Podobnie moŜna uŜyć operatora 

 dla innych składowych obiektu, na przykład: 

 
this







y = 10; 

x  =  this







pobierzX(); 

this







ustawY(5); 

 
 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               15 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

void   ustawWspolrzedne(TPunkt   punkt); 

void   TPunkt::ustawWspolrzedne(TPunkt   punkt) 

x  =  punkt.x; 
y  =  punkt.y; 

 

 
Sekwencja działania instrukcji   pierwszyPunkt.ustawX(100);  na obiekcie  
pierwszyPunkt klasy TPunkt  wygląda następująco. 
 

 

 
Rys. 5. Ustawianie wartości pola x obiektu pierwszyPunkt
 

V.

 

PrzeciąŜanie metod 

 

Obiekt jako argument 

 
Argumentem przekazywanym metodzie moŜe być równieŜ obiekt, na przykład: 

 
 
 

Definicja metody:  

 
 
 
 
 
 
 

 

pierwszyPunkt 
 

pierwszyPunkt.ustawX(100); 

void TPunkt::ustawX(int  x) 

zmienna x ma wartość 100 

 

100 

 

100 

 
Pole x 
 
 
Pole y 

100 

background image

16 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

class   TPunkt 

public: 
int  x;  
int  y; 
 
int  pobierzX(); 
int  pobierzY(); 
void ustawX(int   wspX); 
void ustawY(int   wspY); 
void   ustawWspolrzedne(TPunkt   punkt); 
}; 

#include  <iostream> 
#include  "Punkt5.h" 
using namespace std; 
int TPunkt::pobierzX() 
{  return x;  } 
int TPunkt::pobierzY() 
{  return y;  } 
void TPunkt::ustawX(int   wspX) 
{  x = wspX;  } 
void TPunkt::ustawY(int   wspY) 
{  y = wspY;  } 
void TPunkt::ustawWspolrzedne(TPunkt   punkt) 
{  x  =  punkt.x;   y  =  punkt.y;  } 
 
int main() 

   TPunkt  pierwszyPunkt, drugiPunkt; 
   pierwszyPunkt.ustawX(100); 
   pierwszyPunkt.ustawY(200); 
   drugiPunkt.ustawWspolrzedne(pierwszyPunkt); 
   cout << "x= "<< pierwszyPunkt.pobierzX() << ", "; 
   cout << "y= "<< pierwszyPunkt.pobierzY() << endl; 
   cout << "x= "<< drugiPunkt.pobierzX() << ", "; 
   cout << "y= "<< drugiPunkt.pobierzY() << endl; 
   system("pause"); 
   return 0; 

 
Przykład programu wykorzystującego ten sposób przekazywania parametrów: 

 
 
 
 
 
 
 
 
 
 
 
 
 
 

Plik Punkt5.h 
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Plik Punkt5.cpp 
 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               17 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

class   TPunkt 

public: 
int  x;  
int  y; 
 
int  pobierzX(); 
int  pobierzY(); 
void ustawX(int   wspX); 
void ustawY(int   wspY); 
void   ustawWspolrzedne(TPunkt   punkt); 
void   ustawWspolrzedne(int   wspX, int   wspY); 
}; 

void TPunkt::ustawWspolrzedne(TPunkt   punkt) 

x  =  punkt.x; 
y  =  punkt.y; 

void   TPunkt::ustawWspolrzedne(int   wspX, int   wspY) 

x  =  wspX; 
y  =  wspY; 

 

Overloading 

 
W języku C++ moŜliwe jest tzw. przeciąŜanie metod (ang. overloading). Polega ono na 
zdefiniowaniu wielu metod o tej samej nazwie, ale róŜniących się argumentami 
wywołania. OtóŜ w jednej klasie moŜe istnieć wiele metod o takich samych nazwach, 
co nie znaczy wcale Ŝe są to te same metody. RóŜnią się one bowiem listą argumentów 
przekazywanych w trakcie ich wywoływania. Tą moŜliwość języka C++ nazywamy 
przeciąŜaniem metod
 
Oto przykład zmodyfikowanej deklaracji klasy TPunkt zawierającej dwie metody o tej 
samej nazwie void   ustawWspolrzedne : 
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
Plik Punkt5.h 
 
Argumenty oraz kody tych metod róŜnią się między sobą i wyglądają następująco: 

 
 
 
 
 
 
 
 
 
 
 
 

 
Plik Punkt5.cpp 
 
 

background image

18 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

#include  <iostream> 
#include  "Punkt5.h" 
using namespace std; 
int TPunkt::pobierzX() 

return x; 

int TPunkt::pobierzY() 

return y; 

void TPunkt::ustawX(int   wspX) 

x = wspX; 

void TPunkt::ustawY(int   wspY) 

y = wspY; 

void TPunkt::ustawWspolrzedne(TPunkt   punkt) 

x  =  punkt.x; 
y  =  punkt.y; 

void  TPunkt::ustawWspolrzedne(int   wspX, int   wspY) 

x  =  wspX; 
y  =  wspY; 

int main() 

   TPunkt  pierwszyPunkt, drugiPunkt; 
   pierwszyPunkt.ustawWspolrzedne(100, 200); 
   drugiPunkt.ustawWspolrzedne(pierwszyPunkt); 
   cout << "x= "<< pierwszyPunkt.pobierzX() << ", "; 
   cout << "y= "<< pierwszyPunkt.pobierzY() << endl; 
   cout << "x= "<< drugiPunkt.pobierzX() << ", "; 
   cout << "y= "<< drugiPunkt.pobierzY() << endl; 
   system("pause"); 
   return 0; 

 
Po skompilowaniu i uruchomieniu poniŜszego przykładowego programu Punkt5.cpp

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
Na ekranie pojawią się następujące wyniki: 
x= 100, y= 200 
x= 100, y= 200 
 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               19 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

void FunA(int  X) 

X++; 

 

VI.

 

Sposoby przekazywania argumentów 

 
 
Argumenty metod mogą być przekazywane na dwa sposoby: 

 

przez wartość (ang. value

 

przez referencję (ang. reference

 
Sposób pierwszy polega na tym, Ŝe wartość przekazywana funkcji (zmienna K) nie 
ulega zmianie po zakończeniu działania funkcji funA. Wewnątrz funkcji FunA nie ma 
dostępu do zmiennej K.  
 

 

 
Rys. 6. Przekazywanie wartości argumentu X przez wartość. 
 
Definicja funkcji funA

 
 
 
 
 
 

 
 

FunA(K); 

void FunA(int  X) 

zmienna X ma wartość 10 
zmienna K ma wartość 10 

 

10 

 

10 

K  = 10; 

zmienna K ma wartość 10 

 

X++; 

zmienna X ma wartość 11 
zmienna K ma wartość 10 

cout  << K << endl; 

zmienna K ma wartość 10 
 

background image

20 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

void FunB(int  &X) 

X++; 

 
 

 

Sposób przez referencję  

 
Sposób drugi polega na tym, Ŝe wartość przekazywana funkcji (zmienna K) ulega 
zmianie po zakończeniu działania funkcji, zostaje zmodyfikowana przez funkcję funB
Wewnątrz funkcji FunB wszelkie zmiany dokonywane na zmiennej X odbywają się tak 
jakby to była zmienna K.   
 

 

 
Rys. 7. Przekazywanie wartości argumentu X przez referencję. 
 
Definicja funkcji funB

 
 
 
 
 
 

 
Obie funkcje FunA i FunB na pozór róŜnią się nieznacznie a mianowicie jednym 
znakiem &. Znak ten oznacza operator referencji. 
 

FunB(K); 

void FunB(int  &X) 

zmienna K jest traktowana tak 
samo jak zmienna X  

 

10 

 

10 

K  = 10; 

zmienna K ma wartość 10 

 

X++; 

zmienna X ma wartość 11 
zmienna K ma wartość 11 
 

cout  << K << endl; 

zmienna K ma wartość 11 
 

 

11 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               21 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

klasa*   nazwa_obiektu   =  new   klasa(); 

TPunkt*   punkt   =  new   TPunkt(); 

(*punkt).x   =  100; 

 

VII.

 

Dynamiczne obiekty 

 
 
Aby utworzyć zmienną dynamiczną, korzysta się z operatora new  w następującej 
konstrukcji:  
 
typ*  nazwa_zmiennej   =  new  typ; 
 
Przykład: 
int*  pLiczba  = new  int; 
 
Odwołanie do miejsca wskazywanego przez  pLiczba odbywa się za pomocą operatora 
*, na przykład: 
 
*pLiczba   =  100; 
 
W przypadku klas i obiektów jest podobnie. Aby dynamicznie utworzyć nowy obiekt 
danej klasy, naleŜy zastosować konstrukcję: 
 

 
 
 

 
Dla klasy TPunkt  zdefiniowanej w poprzednich rozdziałach, dynamiczny obiekt  
będzie tworzony za pomocą następującej instrukcji: 
 

 
 

 
W tym przypadku nazwa  punkt  nie będzie obiektem, tylko wskaźnikiem do obiektu
 
Odwoływanie się do składowych obiektu do którego nie ma bezpośredniego dostępu, 
jest juŜ trochę trudniejsze, polega ono na uŜyciu: 



 

operatora wyłuskania (*), 



 

operatora dostępu do składowych (

)   



 

oraz nawiasów okrągłych. 

 
Przypisanie składowej x (pole x) w obiekcie wskazywanym przez wskaźnik punkt
wartości 100 będzie miało następująca postać: 
 

 
 
 

Po lewej stronie znaku = wykonane będą kolejno następujące czynności: wyłuskanie 
obiektu, a potem udostępnione pole x
 
 

background image

22 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

(*punkt).ustawX(100); 

wskaźnik







nazwa_pola 

wskaźnik







nazwa_metody(argumenty) 

punkt)







x  = 100; 

punkt)







ustawX(100); 

 

void  Punkt::inicjuj() 

this







x  = 0; 

this







y  = 0; 


 

 
 
Z kolei uruchomienie metody ustawX na obiekcie wskazywanym przez wskaźnik 
punkt, będzie miało następująca postać: 

 
 
 

 
Istnieje jeszcze inny sposób dostępu (częściej stosowany) do składowych obiektu – 
polega on na uŜyciu operatora 

. 

 
Dostęp do obiektu danej klasy, wskazywanego przez wskaźnik wykonuje się stosując 
następującą  konstrukcję: 
 

 
 
 

lub 

 
 
 

 
Przykłady uŜycia tej drugiej metody: 

 
 
 
 

 
 
Przypomnienie: gdy obiekty lub zmienne proste są tworzone dynamicznie za pomocą 
operatora new, koniecznie naleŜy pamiętać, aby po ich wykorzystaniu usunąć je ze 
sterty za pomocą operatora delete. W przeciwnym razie nastąpią tzw. wycieki pamięci. 
 
 

Inicjalizacja pól 

 
W momencie tworzenia obiektu, warto wiedzieć jakie wartości początkowe mają jego 
pola. Wartości początkowe zaleŜą od kompilatora, i zazwyczaj mają one wartości 
trudne do przewidzenia. Problem ten moŜna usunąć pisząc własna metodę inicjalizacji 
np. 

 
 
 
 
 
 
 

Ale równieŜ moŜe się zdarzyć, Ŝe programista zapomni o jej wywołaniu, nie jest to 
dobre rozwiązanie. 
 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               23 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

class  nazwa_klasy 

public: 
// definicje pól 

nazwa_klasy

(); 

// definicje metod 
}; 

class   TPunkt 

public: 
int  x; 
int  y; 
TPunkt(); 
// definicje pozostałych metod 
}; 

TPunkt ::TPunkt() 

x  =  0; 
y  = 0; 

 

 
 

Konstruktor 

 
Z pomocą w inicjowaniu pól obiektów przychodzi nam konstruktor. 
Konstruktor to specjalna metoda wywoływana automatycznie podczas tworzenia 
obiektu
, nadaje się zatem doskonale do jego wstępnej inicjalizacji. 
  
Tworząc dobrze przemyślany konstruktor, nie trzeba się przejmować inicjalizowaniem 
wartości składowych podczas tworzenia obiektu.   
 
Metoda będąca konstruktorem nie zwraca Ŝadnego wyniku. Przed nazwą konstruktora 
nie moŜe pojawić się nawet słowo void. Nazwa takiej metody musi być identyczna z 
nazwą klasy, której dotyczy. Konstruktor wchodzi w skład klasy. 
 
Ogólna deklaracja klasy posiadającej konstruktor wygląda następująco 

 
 
 
 
 
 
 
 
 

 
Przykład deklaracji klasy TPunkt 

 
 
 
 
 
 
 
 
 
 

 
Przykład definicji konstruktora TPunkt 

 
 
 
 
 
 
 

 
 
 

background image

24 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

class  nazwa_klasy 

public: 
// definicje pól 

~

nazwa_klasy

(); 

// definicje metod 
}; 

class   TPunkt 

public: 
int  x; 
int  y; 

~

TPunkt(); 

// definicje pozostałych metod 
}; 

TPunkt ::

~

TPunkt() 


cout<<”Wywołano destruktor”<< endl; 

 
 

Destruktor 

 
Konstruktory to metody wykonywane podczas tworzenia nowego obiektu. Z kolei 
destruktory to metody wykonywane podczas usuwania obiektu (wykonanie instrukcji 
delete dla obiektów tworzonych dynamicznie lub gdy obiekt będzie usuwany z pamięci 
podczas kończenia pracy programu – dla obiektów statycznych). 
 
Aby zdefiniować destruktor uŜywa się podobnej konstrukcji jak dla konstruktora, tylko 

przed jego nazwą umieszcza się znak 

~

 (tylda). 

 
Ogólna deklaracja klasy posiadającej konstruktor wygląda następująco 

 
 
 
 
 
 
 
 
 

 
Przykład deklaracji klasy TPunkt 

 
 
 
 
 
 
 
 
 
 

 

Przykład definicji konstruktora   

~

TPunkt 

 
 
 
 
 
 

 
Destruktor przydaje się w sytuacjach gdy trzeba posprzątać po obiekcie. Gdy podczas 
pracy obiektu, konstruktor zarezerwuje pamięć lub inne zasoby systemowe, to przed 
usunięciem obiektu
 naleŜy za pomocą destruktora wszystkie jego zasoby zwolnić.  
 
 
 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               25 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

// Program demonstracyjny 
#include <iostream> 
using namespace std; 
 
class Example 

public: 
   int*  pole1; 
   Example() 
   { 
   pole1  = new  int; 
   *pole1 = 0; 
   cout <<"Wywolanie konstruktora"<<endl; 
   } 
 
   ~Example() 
   { 
   delete pole1; 
   cout <<"Wywolanie destruktora"<<endl; 
   } 
}; 
 
int main() 

   Example   example; 
   system("pause"); 
   return 0; 

 
PoniŜszy program DemoUnit1.cpp demonstruje działanie konstruktora i destruktora 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
Program DemoUnit1.cpp 
 

Zadanie VII-1 

 
W funkcji main() dopisz dwie instrukcje: zapisującą wartość 100 do wartości 
wskazywanej przez pole1 w obiekcie example, odczytującą wartość wskazywaną przez 
pole1 z obiektu example
 

Zadanie VII-2 

 
W jaki sposób w funkcji main() będzie wyglądał zapis i odczyt wartości wskazywanej 
przez pole1 obiektu klasy  Example, jeśli zostanie on utworzony przy pomocy 
instrukcji Example  *example  =  new  Example() ? 
 

background image

26 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

class TPunkt 

public: 
   int  x; 
   int  y; 
 
   TPunkt(int   x,  int   y); 
}; 

TPunkt::TPunkt( int   x  =  0,  int   y  =  0); 

this







x  =  x; 

this







y  =  y; 

}; 

 

Zadanie VII-3 

 
Jak będzie wyglądał kod klasy TPunkt w którym wartości x i y byłyby przechowywane 
na stercie, a w obiektach klasy TPunkt znajdowałyby się tylko wskaźniki int* xint* y.  
 

Zadanie VII-4 

 
Proszę napisać kod klasy TKontener, zachowująca się podobnie jak dynamiczna 
tablica przechowująca dodatnie wartości całkowite. Będzie ona miała dwie metody  
get() i set() pobierające i ustawiające wartości poszczególnych komórek. Rozmiar 
tablicy będzie się w razie konieczności zwiększał automatycznie podczas dodawania 
nowych danych. Przykładowo set(2,10) ma spowodować przypisanie wartości 10 do 
drugiej komórki, a get(20) ma pobrać wartość dwudziestej komórki. 
 
 

VIII.

 

Konstruktory 

 
 
 

Argumenty konstruktorów 

 
Konstruktory, tak jak inne metody mogą być bezargumentowe lub przyjmować 
argumenty. Mogą teŜ mieć argumenty domyślne. Deklaracja klasy TPunkt zawierającej 
konstruktor moŜe wyglądać następująco: 

 
 
 
 
 
 
 
 
 
 

a definicja konstruktora: 

 
 
 
 
 
 
 

 
 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               27 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

#include <iostream> 
#include "konstruktor1Unit.h" 
using namespace std; 
TPunkt::TPunkt( int   x  =  0,  int   y  =  0) 

This







x  =  x; 

This







y  =  y; 

}; 
 
int main() 

   TPunkt punkt1; 
   TPunkt punkt2(100); 
   TPunkt punkt3(200, 300); 
   cout << "punkt1: "<<endl; 
   cout << "x= "<<punkt1.x<<" y= "<<punkt1.y<<endl; 
   cout << "punkt2: "<<endl; 
   cout << "x= "<<punkt2.x<<" y= "<<punkt2.y<<endl; 
   cout << "punkt3: "<<endl; 
   cout << "x= "<<punkt3.x<<" y= "<<punkt3.y<<endl; 
   cout << "punkt4: "<<endl; 
   cout << "x= "<<punkt4







x<<" y= "<<punkt4





y<<endl; 

   system("pause"); 
   return 0; 

Program demonstrujący trzy sposoby tworzenia obiektu klasy TPunkt

 

nie podając Ŝadnego argumentu TPunkt  punkt1

 

podając tylko jeden argument TPunkt  punkt2(100)

 

podając oba argumenty TPunkt  punkt3(200, 300)

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Program konstruktory1Unit.cpp 
 
Wynik działania programu: 
punkt1: 
x= 0 y= 0 
punkt2: 
x= 100 y= 0 
punkt3: 
x= 200 y= 300 
punkt4: 
x= 1 y= 2 
 
W przypadku czwartego punktu, na stercie zainicjalizowano obszar, zawierający dwa 
pola x i y , które zainicjowano wartościami 1 i 2. Nazwa punkt4 jest wskaźnikiem do 
tego obszaru (obiektu). 
 
 
 

background image

28 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

#include <iostream> 
#include "konstruktor2Unit.h" 
using namespace std; 
TPunkt::TPunkt( int   x  =  0,  int   y  =  0) 

this->x  =  x; 
this->y  =  y; 
}; 
 
int main() 

   TPunkt punkt1(100, 200); 
   TPunkt punkt2(punkt1); 
   cout << "punkt1: "<<endl; 
   cout << "x= "<<punkt1.x<<" y= "<<punkt1.y<<endl; 
   cout << "punkt2: "<<endl; 
   cout << "x= "<<punkt2.x<<" y= "<<punkt2.y<<endl; 
   system("pause"); 
   return 0; 

 

Konstruktor kopiujący 

 
Do stworzenia kilku obiektów tej samej klasy moŜna uŜyć konstruktora kopiującego.  
 
Co to jest konstruktor kopiujący?  Konstruktor kopiujący to taki konstruktor, którego 
zadaniem jest utworzenie obiektu będącego kopią obiektu juŜ istniejącego. 
 
Jeśli konstruktor kopiujący nie zostanie zdefiniowany oddzielnie, to i tak zostanie on 
automatycznie stworzony – oto przykład programu zawierającego konstruktor 
automatyczny (program konstruktory2Unit.cpp): 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Program konstruktory2Unit.cpp 
 
Instrukcja TPunkt punkt1(100, 200); spowodowała utworzenie obiektu punkt1 o 
współrzędnych x=100 i y=200. następna instrukcja TPunkt punkt2(punkt1);  
utworzyła punkt2 obiekt klasy TPunkt, będący kopią obiektu punkt1. Dlatego jego 
pola x i y zawierają te same wartości co punkt1
 
Uwaga:  
Nawet jeśli nie umieszczono w kodzie własnego konstruktora kopiującego, to i tak 
zostanie on dodany automatycznie. Jego działanie ogranicza się tylko do skopiowania 
obszaru pamięci zajmowanego przez obiekt źródłowy (punkt1) do obszaru 
zajmowanego przez obiekt docelowy (punkt2).  
 
Zagadnienie konstruktora kopiującego nabiera odpowiedniego stopnia powagi, gdy 
zmienimy definicje pól w klasie z typu prostego int na wskaźniki do typu int.  
 
 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               29 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

class TPunkt 

public: 
   int   *x; 
   int   *y; 
 
TPunkt(int   x,  int   y) 

this







x  = new   int(x); 

this







y  = new   int(y); 

}; 

~

TPunkt() 


delete   this







x; 

delete   this







y; 

}; 
}; 

 
 
 

Konstruktor kopiujący i pola wskaźnikowe 

 
W tym rozdziale nastąpi zasadnicza zmiana podejścia do konstruktorów i wskaźników. 
W poniŜszym przykładzie definicja klasy TPunkt będzie zawierać pola x i y będące 
wskaźnikami do typu int.  Ze względu na charakter pól klasy, ulegną zmianie definicje 
konstruktora i destruktora. 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Plik konstruktor3Unit.h
 
Konstruktor tworzy na stercie dwa obszary typu int, ładuje do nich wartości 
argumentów x i y, a do pól x i y przypisuje wskaźniki do zarezerwowanych obszarów. 
 
Destruktor usuwa ze sterty dwa obszary wskazywane przez wskaźniki x i y
 
Reasumując, nazwy x i y nie przechowują danych, lecz wskaźniki do danych, które są 
zapamiętane na stercie. 
 

Zadanie VIII-1 

 
Demonstracja podejścia wskaźnikowego. 
Zmień program konstruktor2Unit.cpp na program konstruktor3Unit.cpp w ten 
sposób, aby zmienić w funkcji main(), sposób dostępu do składowych obiektów: 
 
 
 
 

background image

30 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

int main() 

   TPunkt punkt1(100, 200); 
   TPunkt punkt2(punkt1); 
   cout << "punkt1: "<<endl; 
   cout << "x= "<<*(punkt1.x)<<" y= "<<*(punkt1.y)<<endl; 
   *(punkt2.x) = 1; 
   *(punkt2.y) = 2;    
   cout << "punkt1: "<<endl; 
   cout << "x= "<<*(punkt1.x)<<" y= "<<*(punkt1.y)<<endl; 
   system("pause"); 
   return 0; 

 
Zmień zawartość funkcji main() na następującą: 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
 
Po kompilacji i uruchomieniu programu konstruktor3Unit.cpp, nastąpi niemiła 
niespodzianka – program wykonał nieprawidłowe operacje i nastąpiła interwencja 
systemu operacyjnego.  
 

 

Rys. 8. Komunikat informujący Ŝe w destruktorze próbowano zwolnić pamięć, która juŜ 
wcześniej  została zwolniona. 
 
Druga niespodzianka to fakt, Ŝe za pomocą instrukcji  
   *(punkt2.x) = 1; 
   *(punkt2.y) = 2;    
 
miał zostać zmodyfikowany punkt2, a okazało się, Ŝe został zmodyfikowany punkt1
 

 

Rys. 9. Komunikat pokazujący wcześniejsze wartości x i y oraz późniejsze wartości x i 
y  obiektu punkt1
 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               31 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

Aby przerwać działanie programu i  wrócić do jego projektowania naleŜy uŜyć 
polecenia Run







Program reset (Ctrl+F2). 

 
Przyczyna błędu EAccessViolation
W instrukcji delete   this







x; destruktora dla obiektu punkt2, próbuje się zwolnić 

pamięć juŜ zwolnioną w trakcie uruchomienia destruktora dla obiektu punkt1
 
Przyczyna błędu polegającego na złych wynikach
Problem powstał gdy domyślny konstruktor kopiujący skopiował wskaźniki z obiektu 
punkt1
 do obiektu punkt2. (Rys. 10). Skutkiem tego niedbalstwa, wskaźnik x oraz y po 
prostu rozróŜnia obiektu (nie waŜne czy naleŜy do obiektu punkt1, czy punkt2, zawsze 
wskazuje na ten sam obszar). Natomiast wartości wskazywane nie zostały skopiowane. 
 
 
 

 

 
Rys. 10. Obiekty punkt1punkt2 zawierają wskaźniki wskazujące na te sam obszar. 
 
Aby program działał poprawnie, naleŜy napisać własny konstruktor kopiujący, który dla 
kaŜdego tworzonego jego za pomocą. obiektu będzie rezerwował oddzielną pamięć.  
 
W pliku konstruktor3Unit.h za definicją konstruktora TPunkt(int   x,  int   y) dopisać 
naleŜy nową (własną) definicję konstruktora kopiującego : 
 
TPunkt(TPunkt   &punkt)     // konstruktor kopiujący 

this->x  = new   int(  *(punkt.x)  ); 
this->y  = new   int(  *(punkt.y)  ); 
}; 
 
 
 

punkt1 
 
 
 
 
 
 
punkt2
 
 
 
 
 
 
 
 

int  *x 

int  *y 

int  *x 

int  *y 

 
 
 
 
 
 
 
 
 

obszar  x 

obszar  y 

background image

32 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

class TPunkt 

public: 
   int   *x; 
   int   *y; 
 
TPunkt(int   x,  int   y) 

this->x  = new   int(x); 
this->y  = new   int(y); 
}; 
TPunkt(TPunkt   &punkt) // konstruktor kopiujący 

this->x  = new   int(*(punkt.x)); 
this->y  = new   int(*(punkt.y)); 
}; 
~TPunkt() 

delete   this->x; 
delete   this->y; 
}; 
}; 

 
Tworzenie poprawnego konstruktora kopiującego ilustruje poniŜszy plik 
konstruktor3Unit.h oraz Rys. 11. 
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Plik konstruktor3Unit.h
 

 

Rys. 11. Obiekty punkt1punkt2 zawierają wskaźniki wskazujące na osobne obszary. 
 
 

punkt1 
 
 
 
 
 
 
punkt2
 
 
 
 
 
 
 
 

int  *x 

int  *y 

int  *x 

int  *y 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

obszar  x 

obszar  y 

obszar  x 

obszar  y 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               33 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

class  nazwa_klasy 

public: 

static   nazwa_typu   nazwa_pola

}; 

nazwa_typu   

nazwa_klasy

::

nazwa_pola

 

nazwa_typu   

nazwa_klasy

::

nazwa_pola  

=   wartosc_poczatkowa; 

 

 
 

IX.

 

Składowe statyczne 

 
 
Klasy mogą zawierać składowe statyczne, czyli takie pola i metody, które są dostępne
(wspólne) dla wszystkich obiektów danej klasy. SłuŜą one do komunikowania się 
obiektów między sobą. 
 

Pola statyczne 

 
Aby umieścić statyczne pole wewnątrz klasy, naleŜy wykonać następujące czynności: 
 

 

zadeklarować pole wewnątrz klasy 

 
Ogólna deklaracja klasy posiadającej pole statyczne wygląda następująco 

 
 
 
 
 
 
 

 

 

zdefiniować pole na zewnątrz klasy (poza deklaracją klasy) – czyli 
zarezerwować pamięć dla zmiennej statycznej. NaleŜy wykorzystać operator 
zasięgu :: 

 
Ogólna definicja pola (zmiennej) statycznej wygląda następująco 

 
 
 
 

 
Od tego miejsca w programie faktycznie pole statyczne istnieje i moŜna się do niego 

odwoływać za pomocą operatora zakresu

 ::

 albo operatora 

 (kropka). 

 
Tak zdefiniowana zmienna statyczna ma wartość początkową równa 0 (wykonuje to 
kompilator) Aby ją zainicjować inną wartością naleŜy uŜyć konstrukcji 

 
 
 
 

 
 
 
 

background image

34 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

//program4Unit.cpp 
#include <iostream> 
using namespace std; 
 
class Klasa 

   public: 
   static   int   liczba; 
}; 
 
int Klasa::liczba; 
 
int main() 

   Klasa::liczba = 10; 
   cout << "Klasa::liczba="<<Klasa::liczba<<endl; 
   cout<<endl; 
 
   Klasa example1; 
   Klasa example2; 
 
   example1.liczba = 20; 
   cout << "example1.liczba="<<example1.liczba<<endl; 
   cout << "Klasa::liczba="<<Klasa::liczba<<endl; 
 
   example2.liczba = 30; 
   cout << "example2.liczba="<<example2.liczba<<endl; 
   cout << "Klasa::liczba="<<Klasa::liczba<<endl; 
 
   system("pause"); 
   return 0; 

 
Przykład deklaracji klasy Klasa zawierającej pole statyczne liczba i definicji pola 
statycznego liczba ilustruje program program4Unit.cpp, moŜna przekonać się, Ŝe 
odwołanie do pola statycznego poprzez dowolny obiekt example1 lub example2 jest 

równoznaczne z odwołaniem się poprzez operator zasięgu 

::

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
Program program4Unit.cpp 
 
 
 
 
 
 
 
 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               35 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

class  nazwa_klasy 

public: 

static   typ_zwracany   nazwa_metody

(argumenty_metody); 

}; 

typ_zwracany   

nazwa_klasy

::

nazwa_metody

(argumenty_metody) 


// kod metody 

 

Metody statyczne 

 
W języku C++ mogą istnieć równieŜ statyczne metody. KaŜda statyczna metoda jest 
wspólna dla wszystkich obiektów danej klasy.  
 
Aby umieścić statyczne metodę wewnątrz klasy, naleŜy wykonać następujące 
czynności: 
 

 

zadeklarować metodę wewnątrz klasy 

 
Ogólna deklaracja klasy posiadającej metodę statyczną wygląda następująco 

 
 
 
 
 
 
 

 

 

zdefiniować jej kod na zewnątrz klasy. NaleŜy wykorzystać operator zasięgu :: 

 
Ogólna definicja metody statycznej wygląda następująco 

 
 
 
 
 
 
 

 
 
Przykład deklaracji i definicji metody statycznej Display(), która będzie wyświetlała 
wartość pola statycznego liczba, zawiera zmodyfikowany program program4Unit.cpp
którego treść umieszczono na następnej stronie. 
 
 

Dostęp do pól i metod 

 
Zwykłe metody mają dostęp do wszystkich danych klasy (dostęp do wszystkich pól). 
 
Metody statyczne maja dostęp jedynie do danych statycznych, czyli mogą : 

 

odwoływać się tylko do pól statycznych 

 

wywoływać tylko inne metody statyczne 

 
 
 
 

background image

36 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

//program4Unit.cpp 
#include <iostream> 
using namespace std; 
 
class Klasa 

   public: 
   static int liczba; 
   static void Display(); 
}; 
 
int Klasa::liczba; 
void Klasa::Display() 

cout << "(metoda) liczba = " << liczba << endl; 

 
int main() 

 
   Klasa::liczba = 10; 
   cout << "Klasa::liczba="<<Klasa::liczba<<endl; 
   cout<<endl; 
 
   Klasa example1; 
   Klasa example2; 
 
   example1.liczba = 20; 
   cout << "example1.liczba="<<example1.liczba<<endl; 
   cout << "Klasa::liczba="<<Klasa::liczba<<endl; 
   example1.Display(); 
 
   example2.liczba = 30; 
   cout << "example2.liczba="<<example2.liczba<<endl; 
   cout << "Klasa::liczba="<<Klasa::liczba<<endl; 
   example2.Display();    
 
   system("pause"); 
   return 0; 

 
 
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
Program zmodyfikowany program4Unit.cpp
 
 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               37 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

#include <iostream> 
using namespace std; 
 
class Klasa 

   public: 
   int a; 
   static int b; 
   void fun(void); 
   void funA(); 
   void funB(); 
   static void funAA(); 
   static void funBB(); 
}; 
 
int Klasa::b = 1; 
 
void Klasa::funA(void) 

   a = 10; 
   b = 20; 
   funB(); 
   funAA(); 

 
void Klasa::funAA() 

   a = 100; // odwołanie do niestatycznego pola 
   b = 200; 
   funB();   // odwołanie do niestatycznej metody 
   funBB(); 

 
void Klasa::funB() {} 
void Klasa::funBB() {} 
 
int main() 
{    return 0;  } 

 

Dostęp do pól i metod – c.d. 

 
 
Oto program program5Unit.cpp ilustrujący sytuację odwołania się z poziomu metody 
statycznej, do niestatycznych obiektów.  

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
Program program5Unit.cpp
 

background image

38 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

 
 
Po kompilacja programu program5Unit.cpp  zakończy się dwoma komunikatami  
 
program5Unit.cpp: E2231 Member Klasa::a Cannot be used whitout an object. 
program5Unit.cpp: E2283 Member Use . or -> to call Klasa::funB(). 
 
Pierwszy błąd  powstał w instrukcji 
  
a = 100;  
 
spowodowany tym, Ŝe metoda statyczna funAA odwołuje się do niestatycznego pola a
 
Drugi błąd  powstał w instrukcji 
  
funB();  
 
spowodowany tym, Ŝe metoda zwykła funB() jest wywoływana w metodzie statycznej 
funAA()
 
 

Zadanie IX-1 

 
Napisz kod przykładowej klasy TOsoba, której zadaniem będzie przechowywanie 
imion i nazwisk osób. Pola imie i nazwisko powinny być typu char* , a pamięć 
niezbędna do przechowywania danych ma być rezerwowana dynamicznie w 
konstruktorze podczas tworzenia obiektu. Pamiętaj o uwzględnieniu konstruktora 
kopiującego oraz destruktora. 
 

Zadanie IX-2 

 
Napisz kod przykładowej klasy TNapis, której zadaniem będzie przechowywanie ciągu 
znaków. Pole dane powinno być typu char* , a pamięć niezbędna do przechowywania 
danych ma być rezerwowana dynamicznie w konstruktorze podczas tworzenia obiektu.  
Klasa powinna posiadać metodę o nazwie Dlugosc zwracającą liczbę znaków danej 
przechowywanej w polu dane. Pamiętaj o uwzględnieniu konstruktora kopiującego oraz 
destruktora. 
 
 

Zadanie IX-3 

 
Napisz kod przykładowej klasy TKlasa, zawierającej pole statyczne count, którego 
zadaniem będzie przechowywanie aktualnej liczby obiektów tej klasy.  
 
 
 
 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               39 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

class   TPunkt 

public: 
int  x; 
int  y; 
TPunkt(); 
~TPunkt(); 
int     pobierzX(); 
int     pobierzY(); 
void   ustawX(int   wspX); 
void   ustawY(int   wspY); 
void   ustawWspolrzedne(TPunkt   punkt); 
void   ustawWspolrzedne(int   wspX, int   wspY); 
}; 

class  nazwa_klasy_potomnej : public   nazwa_klasy_bazowej 

public: 
// definicja klasy potomnej 
}; 

 

X.

 

Dziedziczenie  

 
 
Dziedziczenie to jedna z podstawowych technik programowania obiektowego.  
Dziedziczenie realizowane jest za pomocą symbolu : (dwukropek) , w następującej 
konstrukcji 

 
 
 
 
 
 
 

gdzie: 

 

klasa potomna (klasa podrzędna, podklasa) to nowa klasa przejmująca 
(dziedzicząca) składowe klasy bazowej, 

 

klasa bazowa (klasa podstawowa, klasa nadrzędna, nadklasa) to klasa juŜ 
zdefiniowana, słuŜąca jako pewien wzorzec dla nowej klasy potomnej. 

  
Przykładem klasy bazowej moŜe być definicja klasy TPunkt – reprezentująca punkt na 
płaszczyźnie (plik punkt6.h). 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
Plik punkt6.h
 
Aby utworzyć reprezentację punktu w przestrzeni trójwymiarowej, naleŜałoby stworzyć 
definicję nowej klasy o nazwie TPunkt3D. MoŜna ją tworzyć od nowa, by uwzględnić 
trzy współrzędne x,y,z.  
 
 
 

background image

40 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

class   TPunkt3D : public TPunkt 

public: 
int  z; 
TPunkt3D(); 
~TPunkt3D(); 
int     pobierzZ(); 
void   ustawZ(int   wspZ); 
void   ustawWspolrzedne(TPunkt3D   punkt); 
void   ustawWspolrzedne(int   wspZ); 
}; 

 
MoŜna wykorzystać fakt, Ŝe dla klasy TPunkt juŜ zostały zdefiniowane odpowiednie 
pola (x, y) oraz napisane odpowiednie metody obsługujące współrzędne (x,y)  i dopisać 
po prostu nowe pole z oraz metody obsługujące trzeci wymiar (Rys. 13).  
 
Wybór tej drugiej metody nazywamy dziedziczeniem.  
 
Następuje więc dziedziczenie gotowych rozwiązań z klasy bazowej TPunkt 
(reprezentującej punkt na płaszczyźnie) do nowej klasy potomnej TPunkt3D
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 

Ciąg dalszy pliku punkt6.h
 
W ten oto sposób programista nie namęczył się wiele, bowiem dopisał tylko: 
pole z,   oraz metody: 

 

TPunkt3D() 

 

~TPunkt3D() 

 

pobierzZ() 

 

ustawZ() 

 

ustawWspolrzedne() 

 
Aby przekonać się jak zachowują się obiekty klasy potomnej TPunkt3D wystarczy 
napisać krótki program, demonstrujący technikę dziedziczenia – patrz program w pliku 
punk6.cpp.  
 
Wynik działania programu to: 
Konstruktor TPunkt 
Konstruktor TPunkt3D 
Konstruktor TPunkt 
Konstruktor TPunkt3D 
10 
20 
30 



 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               41 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

#include <iostream> 
#include "Punkt6.h" 
using namespace std; 
//==== klasa bazowa ==== 
TPunkt::TPunkt() 

cout<<"Konstruktor TPunkt"<< endl; 
x = 0; 
y = 0; 

TPunkt ::~TPunkt() 

 

 
Rys. 12. Dziedziczenie składowych klasy TPunkt, do klasy potomnej TPunkt3D
 
Plik punk6.cpp  

 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
 

Klasa bazowa TPunkt 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

int  x 
int  y 
TPunkt() 
~TPunkt() 
pobierzX() 
pobierzY() 
ustawX() 
ustawY() 
ustawWspolrzedne() 

Klasa potomna TPunkt3D 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Składowe 

dopisane 

Składowe 

dziedziczone 

Nowe (dopisane): 

int  z; 
TPunkt3D() 
~TPunkt3D() 
pobierzZ() 
ustawZ() 
ustawWspolrzedne() 

 

background image

42 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

int TPunkt::pobierzX() 

return x; 

int TPunkt::pobierzY() 

return y; 

void TPunkt::ustawX(int   wspX) 

x = wspX; 

void TPunkt::ustawY(int   wspY) 

y = wspY; 

void TPunkt::ustawWspolrzedne(TPunkt   punkt) 

x  =  punkt.x; 
y  =  punkt.y; 

void TPunkt::ustawWspolrzedne(int   wspX, int   wspY) 

x  =  wspX; 
y  =  wspY; 

//==== klasa potomna ==== 
TPunkt3D::TPunkt3D() 

cout<<"Konstruktor TPunkt3D"<< endl; 
z = 0; 

TPunkt3D ::~TPunkt3D() 


int TPunkt3D::pobierzZ() 

return z; 

void TPunkt3D::ustawZ(int   wspZ) 

z = wspZ; 

 
Plik punk6.cpp – ciąg dalszy  

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
 
 
 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               43 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

void TPunkt3D::ustawWspolrzedne(TPunkt3D   punkt) 

z  =  punkt.z; 

void TPunkt3D::ustawWspolrzedne(int   wspZ) 

z  =  wspZ; 

 
 
int main() 

   TPunkt3D  punkt1; 
   punkt1.ustawX(10); 
   punkt1.ustawY(20); 
   punkt1.ustawZ(30); 
   TPunkt3D  punkt2; 
 
   cout << punkt1.x << endl; 
   cout << punkt1.y << endl; 
   cout << punkt1.z << endl; 
 
   cout << punkt2.x << endl; 
   cout << punkt2.y << endl; 
   cout << punkt2.z << endl; 
   system("pause"); 
   return 0; 

 
Plik punk6.cpp – ciąg dalszy  

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
 
 
Stosując dziedziczenie waŜną kwestią jest zachowanie się konstruktorów klasy bazowej 
i potomnej. Jeśli w klasie bazowej istnieje konstruktor, który moŜna wywołać bez 
parametrów (konstruktor domyślny TPunkt),  to podczas tworzenia obiektów klasy 
potomnej najpierw wykonywany jest konstruktor klasy bazowej a potem konstruktor 
klasy potomnej (TPunkt3D). 
 
 
 
 
 
 
 
 
 
 
 

background image

44 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

 

XI.

 

Dostęp do składowych klasy 

 
W C++ programista moŜe decydować o sposobie dostępu do składowych klasy. Do tego 
celu słuŜą modyfikatory dostępu (ang. access modifiers), zwane równieŜ 
specyfikatorami. KaŜda składowa moŜe być: 

 

publiczna (public), 

 

prywatna (private), 

 

chroniona (protected). 

 

Składowe publiczne 

 
Dostęp do składowych publicznych jest nieograniczony, moŜna się do nich odwoływać 
bezpośrednio. 
 

Składowe prywatne 

 
Dostęp do składowych prywatnych jest ograniczony tylko i wyłącznie do metod 
zdefiniowanych w danej klasie (oraz do funkcji zaprzyjaźnionych). 
 

Składowe chronione 

 
Dostęp do składowych chronione mają tylko metody zdefiniowane w danej klasie i 
klasach pochodnych
 
Jeśli nie zastosujemy Ŝadnego modyfikatora, to składowe klasy zostaną potraktowane 
tak, jakby wystąpił modyfikator private. PoniŜsze definicje klasy są równowaŜne: 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Aby sprawdzić, czy do składowej prywatnej moŜna się odwołać,  
napisz program program1.cpp, który pokaŜe czy jest to moŜliwe. 
Przy próbie kompilacji programu, kompilator wyświetli błąd  
 
[C++ Error] E2247 ‘Bazowa::x’  is not  accessible 

class  nazwa_klasy 

// definicja wnętrza klasy 
}; 

class  nazwa_klasy 

private: 
// definicja wnętrza klasy 
}; 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               45 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

Jeśli pole x  jest prywatne, to instrukcja odwołująca się do niego jest błędna:  
obiekt1.x = 100; 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
program1.cpp 
 
Jeśli do składowych prywatnych nie moŜna się odwoływać bezpośrednio, to w jaki 
sposób zmieniać ich wartości? Najlepszym sposobem na to jest dopisanie publicznych 
metod operujących na składowych prywatnych. Umieść w klasie Bazowa metody getX 
setX. Pierwsza będzie zwracała wartość pola x. a druga będzie przypisywała polu x 
wartość argumentu o nazwie x. Ilustruje to program program2.cpp
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
program2.cpp 
 

class  Bazowa 

private: 
 

int  x; 

public: 
 

int  y; 

}; 
 
int main() 

    Bazowa  obiekt1; 
    obiekt1.x = 100; 
    obiekt1.y = 200; 
}; 

#include <iostream> 
using namespace std; 
class  Bazowa 

private: 
 

int  x; 

public: 
 

int  y; 

 

int getX() { return x;}; 

 

void setX(int  x) 

 

{ this -> x = x; }; 

}; 
int main() 

    Bazowa  obiekt1; 
    obiekt1.setX(100); 
    obiekt1.y = obiekt1.getX(); 
    cout  << obiekt1.getX()  <<  endl; 
    cout  << obiekt1.y   <<  endl; 
    system("pause"); 
}; 

background image

46 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

 

XII.

 

Modyfikatory i dziedziczenie  

 
Sprawdź teraz jak działają modyfikatory przy dziedziczeniu. W programie 
program3.cpp definiujemy dwie klasy Bazowa i Pochodna (klasa Pochodna 
dziedziczy z klasy Bazowa). W klasie bazowej zdefiniuj trzy składowe: 
x – pole prywatne, 
y – pole publiczne, 
z – pole chronione. 
 
W klasie pochodnej zdefiniuj sześć publicznych metod zajmujących się ustawianiem i 
pobieraniem wartości poszczególnych pól. Następnie w funkcji main utwórz obiekt 
klasy Pochodna oraz wywołaj jego metody setY i setZ, a na koniec sprawdź, czy 
moŜliwe jest odwołanie się do pól y i z
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
program3.cpp 
 

class  Bazowa 

   private: 
    

int  x; 

   public: 
 

   int  y; 

   protected: 
      int z; 
}; 
 
class Pochodna: public Bazowa 

   public: 
      int getX()  {return x; }; 
      int getY()  {return y; }; 
      int getZ()  {return z; }; 
      void setX(int x) {this->x = x; }; 
      void setY(int y) {this->y = y; }; 
      void setZ(int z) {this->x = z; }; 
}; 
 
int main() 

    Pochodna  obiekt1; 
    obiekt1.setY(100); 
    obiekt1.setZ(200); 
    obiekt1.y = obiekt1.z; 
    obiekt1.y = obiekt1.getZ(); 
}; 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               47 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

 
Przy próbie kompilacji programu program3.cpp, kompilator wyświetli błędy: 
[C++ Error] E2247 ‘Bazowa::x’  is not  accessible  
[C++ Error] E2247 ‘Bazowa::z’  is not  accessible 
 
Nieprawidłowości w programie program3.cpp to: 
 
Deklaracje: 
 
 
 
 
 
 
 
 
 
 
 
są błędne, bo klasa pochodna nie ma dostępu do prywatnych składowych klasy 
bazowej. 
 
Instrukcja  
 
 
 
 
jest błędna, poniewaŜ do pola chronionego nie moŜna się odwoływać bezpośrednio. 
 
 
UWAGA: 
Przeczytaj uwaŜnie tekst w ramce „Reguły budowania klas potomnych” (Rys. 13). 
 

Praktyczny cel stosowania modyfikatorów 

 
Modyfikatory private i protected pozwalają na ukrywanie wnętrza klasy (pola klasy), a 
na zewnątrz udostępnienie tylko tzw. interfejsu klasy (metody publiczne). Ukrywanie 
wnętrza obiektu (klasy) nazywamy hermetyzacją i jest to jedna z głównych cech 
programowania obiektowego. Dla programisty korzystającego z gotowych klas 
powinny być dostępne tylko metody operujące na polach (właściwościach) klasy 
(obiektu). W ten sposób autor klas moŜe w sposób niezauwaŜalny zmieniać 
reprezentację wewnętrzną klasy, a korzystający z niej nie musi się tymi zmianami 
przejmować. 
 
 
 
 
 
 

int getX()  {return x; }; 
 
void setX(int x)  

this->x = x;  
}; 

 

obiekt1.y = obiekt1.z; 

background image

48 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

 

Reguły budowania klas potomnych 

 

 

 
Rys. 13. Reguły budowania klas potomnych. 
 

class potomna : modyfikator klasa_bazowa 

// definicja klasy potomnej 
}; 

Schemat budowania klasy potomnej moŜna ogólnie przedstawić jako: 

Oznacza to, Ŝe klasa potomna ma wpływ na to, w jaki sposób będą 
dziedziczone składowe klasy bazowej. MoŜna zatem zmieniać reguły 
dostępu. Jedynymi składowymi, których zachowania nie moŜna zmienić, są 
składowe prywatne. W dwóch pozostałych przypadkach obowiązują 
następujące reguły: 

1.

 

jeŜeli przed nazwą klasy bazowej wystąpi modyfikator public, to w 
klasie potomnej wszystkie składowe publiczne pozostają 
publicznymi, a wszystkie składowe chronione pozostają chronione

2.

 

jeŜeli przed nazwą klasy bazowej wystąpi modyfikator private, to w 
klasie potomnej wszystkie składowe (publiczne i chronione) 
pozostają prywatnymi

3.

 

jeŜeli przed nazwą klasy bazowej wystąpi modyfikator protected, to 
w klasie potomnej wszystkie składowe publiczne stają się 
chronionymi, a i chronione pozostają chronionymi

class Bazowa 

private: 
 

int  x; 

public: 
 

int  y; 

protected: 
 

int  z; 

 

}; 
 
class
 Pochodna : private Bazowa 

}; 

W przykładowej klasie  
 
Pochodna wszystkie  
 
składowe będą  
 
prywatne i nie będzie  
 
do nich  
 
bezpośredniego  
 
dostępu. 

REGUŁY BUDOWANIA KLAS POTOMNYCH 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               49 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

 
 

Zadanie XII-1 

 
Napisz kod klasy bazowej  TOsoba, której zadaniem będzie przechowywanie imion i 
nazwisk osób. Pola imie i nazwisko powinny być typu char* , a pamięć niezbędna do 
przechowywania danych ma być rezerwowana dynamicznie w konstruktorze podczas 
tworzenia obiektu. Pamiętaj o konstruktorach zwykłych i kopiujących. Napisz klasę 
pochodną TPracownik, dziedziczącej pola i konstruktory klasy TOsoba oraz 
przechowującej w polu stanowisko (char*  stanowisko) określające stanowisko 
zajmowane przez pracownika. Dopisz odpowiednie konstruktory: 
 
TPracownik(char* imie, char* nazwisko, char* stanowisko); //konstruktor 
TPracownik(TPracownik  &pracownik); //konstruktor kopiujący 
~TPracownik(); // destruktor 
 
 

XIII.

 

Przesłanianie składowych klasy 

 
 
Podczas dziedziczenia cech klasy bazowej, klasa pochodna przejmuje składowe klasy 
bazowej. Co się jednak stanie, gdy w klasie pochodnej zdefiniujemy składową o takiej 
samej nazwie?  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
MoŜe spowoduje to konflikt nazw? Nie, kod taki będzie poprawny. W obiektach klasy 
Pochodna będą znajdować się dwa pola (Bazowa::x) i (Pochodna::x).  
 
 

#include  <iostream> 
using namespace std; 
 
class Bazowa 

   public: 
      int x; 
}; 
 
class Pochodna : public Bazowa 

   public: 
      int x; 
}; 

background image

50 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

 
Odwołanie się do pola x  bezpośrednie (np.

 obiekt.x = 2;

 ) spowoduje przesłonięcie 

pola z klasy bazowej Bazowa. Nie ma więc do niej bezpośredniego dostępu. Do tego 
pola x, które jest dziedziczone z klasy bazowej Bazowa mamy dostęp poprzez operator 
zakresu ::. (np. 

obiekt.Bazowa::x = 1;

). 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

XIV.

 

Prosta hierarchia klas 

 
 
Dziedziczenie pozwala na budowanie hierarchii klas czyli na wyprowadzanie z jednej 
klasy bazowej wielu klas pochodnych, np. z ogólnej klasy Pojazd mogłyby dziedziczyć 
takie klasy, jak RowerPociągSamochód. W przykładzie pokazano prostą hierarchię 
dziedziczenia klas A,B,C oraz zachowanie się ich konstruktorów. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

int main() 

   Pochodna  obiekt; 
   obiekt.x = 2; 
   obiekt.Bazowa::x = 1; 
   cout << obiekt.x << endl; 
   cout << obiekt.Bazowa::x << endl; 
   system("pause"); 
   return 0; 

 

class A 

class B 

class C 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               51 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

 
Przykładowy program klasy2Unit1.cpp 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

#include <iostream> 
using namespace std; 
 
class A 

   public: 
      int x; 
      A() {cout<<"Konstruktor klasy A"<<endl;} 
}; 
 
class B : public A 

   public: 
      int y; 
      B() {cout<<"Konstruktor klasy B"<<endl;} 
}; 
 
class C : public B 

   public: 
      int z; 
      C() {cout<<"Konstruktor klasy C"<<endl;} 
}; 
 
int main() 

   C obiekt; 
   obiekt.x = 10; 
   obiekt.y = 20; 
   obiekt.z = 30; 
   cout << obiekt.x << endl; 
   cout << obiekt.y << endl; 
   cout << obiekt.z << endl;    
   system("pause"); 
   return 0; 

background image

52 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

 
 
Instrukcja  
 
 
 
 
 
spowoduje utworzenie obiektu klasy C, która jest pochodną w stosunku do klasy 
nadrzędnej B, z kolei klasa B jest pochodną klasy bazowej A. Spowoduje to, Ŝe 
automatycznie zostaną wywołane konstruktory domyślne (jeśli takie zostały 
zdefiniowane): 
 
Konstruktor klasy A 
Konstruktor klasy B 
Konstruktor klasy C 
 
 
 
 
 
 

XV.

 

Literatura pomocnicza 

 
 
A. Majczak. C++ Przykłady praktyczne. Wydawnictwo Mikom, Warszawa 2003. 
J. Liberty. C++ dla kaŜdego. Wydawnictwo Helion, Gliwice 2002. 
K. Loudon. C++ Leksykon kieszonkowy. Wydawnictwo Helion, Gliwice 2003. 
A. Stasiewicz. C++ Ćwiczenia praktyczne. Wydawnictwo Helion, Gliwice 2004. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

C   obiekt;

 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               53 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

 

XVI.

 

Odpowiedzi do zadań 

 
 

Zadanie VII-1 

 
Zadanie1Unit1.cpp 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

// Program Zadanie1Unit1.cpp 
// Odpowiedź do Zadania VII-1 
#include <iostream> 
using namespace std; 
 
class Example 

public: 
   int*  pole1; 
   Example() 
   { 
   pole1  = new  int; 
   *pole1 = 0; 
   cout <<"Wywolanie konstruktora"<<endl; 
   } 
 
   ~Example() 
   { 
   delete pole1; 
   cout <<"Wywolanie destruktora"<<endl; 
   } 
}; 
 
int main() 

   Example example; 
   *(example.pole1) = 100; 
   cout << *(example.pole1) << endl; 
   system("pause"); 
   return 0; 

background image

54 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

 

Zadanie VII-2 

 
Zadanie2Unit1.cpp 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

// Program Zadanie2Unit1.cpp 
// Odpowiedź do Zadania VII-2 
#include <iostream> 
using namespace std; 
 
class Example 

public: 
   int*  pole1; 
   Example() 
   { 
   pole1  = new  int; 
   *pole1 = 0; 
   cout <<"Wywolanie konstruktora"<<endl; 
   } 
 
   ~Example() 
   { 
   delete pole1; 
   cout <<"Wywolanie destruktora"<<endl; 
   } 
}; 
 
int main() 

   Example *example = new Example(); 
   *(example->pole1) = 100; 
   cout << *(example->pole1) << endl; 
   delete example; 
   system("pause"); 
   return 0; 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               55 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

 

Zadanie VII-3 

 
Zadanie3.h 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Zadanie3Unit1.cpp 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

class   TPunkt 

public: 
   int  *x; 
   int  *y; 
   TPunkt(int x, int y); 
   ~TPunkt(); 
   int  pobierzX(); 
   int  pobierzY(); 
   void ustawX(int   wspX); 
   void ustawY(int   wspY); 
   void   ustawWspolrzedne(TPunkt   &punkt); 
   void   ustawWspolrzedne(int   wspX, int   wspY); 
}; 

#include <iostream> 
#include "Zadanie3.h" 
using namespace std; 
TPunkt::TPunkt(int x = 0, int y = 0)  {   

this->x = new int(x);    
this->y = new int(y);   


TPunkt ::~TPunkt()  { 

delete x; 
delete y; 


int TPunkt::pobierzX() { 

return *x; 


int TPunkt::pobierzY() { 

return *y; 


void TPunkt::ustawX(int   wspX)  { 

*x = wspX; 


void TPunkt::ustawY(int   wspY)  { 

*y = wspY; 

background image

56 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

 
 
 
Zadanie3Unit1.cpp - ciąg dalszy  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Zadanie VII-4 

Zadanie4.h 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

class   TKontener 

public: 
   TKontener(int size); 
   ~TKontener(); 
   int* tab; 
   int size; 
   int get(int index); 
   int set(int index, int value); 
}; 

void TPunkt::ustawWspolrzedne(TPunkt   &punkt) 

*x  =  *punkt.x; 
*y  =  *punkt.y; 

void TPunkt::ustawWspolrzedne(int   wspX, int   wspY) 

*x  =  wspX; 
*y  =  wspY; 

 
int main() 

   TPunkt  punkt(100, 200); 
   cout << punkt.pobierzX() << endl; 
   cout << punkt.pobierzY() << endl; 
   system("pause"); 
   return 0; 

 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               57 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

 
 
Zadanie4Unit1.cpp 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

#include <iostream> 
#include "Zadanie4.h" 
using namespace std; 
TKontener::TKontener(int size)  { 

tab = new int[size]; 
this->size = size; 


TKontener::~TKontener()  { 

delete tab; 


int TKontener::get(int index)  { 

if (index<0 || index > size-1) 

 return -1; 

return tab[index]; 


int TKontener::set(int index, int value)  { 
if (index<0 || index > size-1) 
   { 
   int* newtab = new int[index*2]; 
   for(int i=0; i< size; i++) 
      newtab[i] = tab[i]; 
   delete tab; 
   tab = newtab; 
   size = index * 2; 
   } 
tab[index] = value; 
return 0; 

 
int main() 

   TKontener kontener(5); 
   for (int i=0; i < 5; i++) 
       

kontener.set(i,10); 

   kontener.set(7,1); 
   kontener.set(8,2); 
   for (int i=0; i < 9; i++) 
       

cout << kontener.get(i) << endl; 

   system("pause"); 
   return 0; 

background image

58 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

 

Zadanie IX-1 

Zadanie5Unit1.h 
 
 
 
 
 
 
 
 
 
 
 
 
 
Zadanie5Unit1.cpp 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

class   TOsoba 

public: 
   char* imie; 
   char* nazwisko; 
 
   TOsoba(char* imie, char* nazwisko); //konstruktor 
   TOsoba(TOsoba &osoba); //konstruktor kopiujący 
   ~TOsoba(); // destruktor 
}; 

#include <iostream> 
#include "Zadanie5Unit1.h" 
using namespace std; 
 
TOsoba::TOsoba(char* imie, char* nazwisko) 

int dlugosc = strlen(imie); 
this->imie = new char[dlugosc+1]; 
strcpy(this->imie, imie); 
dlugosc = strlen(nazwisko); 
this->nazwisko = new char[dlugosc+1]; 
strcpy(this->nazwisko, nazwisko); 

 
TOsoba::TOsoba(TOsoba &osoba) 

int dlugosc = strlen(osoba.imie); 
this->imie = new char[dlugosc+1]; 
strcpy(this->imie, osoba.imie); 
dlugosc = strlen(osoba.nazwisko); 
this->nazwisko = new char[dlugosc+1]; 
strcpy(this->nazwisko, osoba.nazwisko); 

 
TOsoba::~TOsoba() 

delete this->imie; 
delete this->nazwisko; 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               59 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Zadanie IX-2 

Zadanie6Unit1.h 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Zadanie6Unit1.cpp 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
int main() 

   TOsoba osoba1("Adam", "Abacki"); 
   cout<<"Dane obiektu osoba1:"<<endl; 
   cout<<osoba1.imie<<" "<<osoba1.nazwisko<<endl;    
   TOsoba osoba2(osoba1); 
   cout<<"Dane obiektu osoba2:"<<endl; 
   cout<<osoba2.imie<<" "<<osoba2.nazwisko<<endl; 
   system("pause"); 
   return 0; 

class   TNapis 

public: 
   char* dane; 
 
   TNapis(); //konstruktor 
   int Dlugosc(void); 
   TNapis(char* tekst); //konstruktor 
   TNapis(TNapis &napis); //konstruktor kopiujący 
   ~TNapis(); // destruktor 
}; 

#include <iostream> 
#include "Zadanie6Unit1.h" 
using namespace std; 
 
TNapis::TNapis() 

dane = new char[1]; 
dane[0] = '\0'; 

 

background image

60 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

int TNapis::Dlugosc(void) 

return strlen(this->dane); 

 
TNapis::TNapis(char* tekst) 

int rozmiar = strlen(tekst) + 1; 
dane = new char[rozmiar]; 
strcpy(this->dane, tekst); 

TNapis::TNapis(TNapis &napis) 

dane = new char[napis.Dlugosc()+1]; 
strcpy(this->dane,napis.dane); 

TNapis::~TNapis() 

delete this->dane; 

int main() 

   TNapis s1; 
   TNapis s2("ABC"); 
   TNapis s3(s2); 
   cout<<"Napis "<<s1.dane<< " ma dlugosc "<<s1.Dlugosc()<<endl; 
   cout<<"Napis "<<s2.dane<< " ma dlugosc "<<s2.Dlugosc()<<endl; 
   cout<<"Napis "<<s3.dane<< " ma dlugosc "<<s3.Dlugosc()<<endl;        
   system("pause"); 
   return 0; 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               61 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

 

Zadanie IX-3 

Zadanie7Unit1.h 
 
 
 
 
 
 
 
 
 
 
 
 
Zadanie7Unit1.cpp 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

class   TKlasa 

public: 
   static int count; 
 
   TKlasa(); //konstruktor 
   ~TKlasa(); // destruktor 
}; 

#include <iostream> 
#include "Zadanie7Unit1.h" 
using namespace std; 
 
int TKlasa::count = 0; 
 
TKlasa::TKlasa() 

count++; 

TKlasa::~TKlasa() 

count– –; 

background image

62 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

 
 

Zadanie XII-1 

PracownikUnit1.h 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
PracownikUnit1.cpp 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

//klasa bazowa 
class   TOsoba 

public: 
   char* imie; 
   char* nazwisko; 
 
   TOsoba(); //konstruktor domyslny 
   TOsoba(char* imie, char* nazwisko); //konstruktor 
   TOsoba(TOsoba &osoba); //konstruktor kopiujący 
   ~TOsoba(); // destruktor 
}; 
 
//klasa pochodna 
class   TPracownik  : public TOsoba 

public: 
   char* stanowisko; 
 
   TPracownik(char* imie, char* nazwisko, char* stanowisko); 
//konstruktor 
   TPracownik(TPracownik &pracownik); //konstruktor kopiujący 
   ~TPracownik(); // destruktor 
}; 

#include <iostream> 
#include "PracownikUnit1.h" 
using namespace std; 
 
//klasa bazowa 
TOsoba::TOsoba() 

cout << "Konstruktor domyslny TOsoba" << endl; 
this->imie = new char[1]; 
strcpy(this->imie, ""); 
this->nazwisko = new char[1]; 
strcpy(this->nazwisko, ""); 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               63 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

 
 
PracownikUnit1.cpp – ciąg dalszy 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

TOsoba::TOsoba(char* imie, char* nazwisko) 

int dlugosc = strlen(imie); 
this->imie = new char[dlugosc+1]; 
strcpy(this->imie, imie); 
dlugosc = strlen(nazwisko); 
this->nazwisko = new char[dlugosc+1]; 
strcpy(this->nazwisko, nazwisko); 

 
TOsoba::TOsoba(TOsoba &osoba) 

int dlugosc = strlen(osoba.imie); 
this->imie = new char[dlugosc+1]; 
strcpy(this->imie, osoba.imie); 
dlugosc = strlen(osoba.nazwisko); 
this->nazwisko = new char[dlugosc+1]; 
strcpy(this->nazwisko, osoba.nazwisko); 

 
TOsoba::~TOsoba() 

cout << "Destruktor TOsoba"<<endl; 
delete this->imie; 
delete this->nazwisko; 

 
//klasa pochodna 
TPracownik::TPracownik(char* imie, char* nazwisko, char* stanowisko) 

strcpy(this->imie, imie); 
strcpy(this->nazwisko, nazwisko); 
 
int dlugosc = strlen(stanowisko); 
this->stanowisko = new char[dlugosc+1]; 
strcpy(this->stanowisko, stanowisko); 

 
TPracownik::TPracownik(TPracownik &pracownik) 

int dlugosc = strlen(pracownik.stanowisko); 
this->stanowisko = new char[dlugosc+1]; 
strcpy(this->stanowisko, pracownik.stanowisko); 

background image

64 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

 
PracownikUnit1.cpp – ciąg dalszy 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
TPracownik::~TPracownik() 

cout << "Destruktor TPracownik"<<endl; 
delete this->stanowisko; 

 
int main() 

   TPracownik pracownik1("Barnaba", "Celinowski", "Kierownik"); 
   cout<<"Dane obiektu pracownik1:"<<endl; 
   cout<<pracownik1.imie<<endl; 
   cout<<pracownik1.nazwisko<<endl; 
   cout<<pracownik1.stanowisko<<endl; 
   system("pause"); 
   return 0; 

background image

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II.                               65 
______________________________________________________________________ 
 

 

©2006 Jerzy Kluczewski 

 

 

SPIS TREŚCI 

 
I. 

Przestrzenie nazw ..................................................................................................... 2 

Przestrzeń nazw std....................................................................................................... 5 

II.  Obiekty...................................................................................................................... 6 

Projekt obiektu .............................................................................................................. 6 

III. 

Klasa ..................................................................................................................... 7 

Klasa TPunkt................................................................................................................. 8 
Pola klasy...................................................................................................................... 8 
Metody klasy................................................................................................................. 8 
Określenie struktury klasy ............................................................................................ 8 
Odwołania do składowych obiektu............................................................................. 11 
Wiele obiektów tej samej klasy .................................................................................. 11 

IV. 

Właściwości obiektu ........................................................................................... 12 

Argumenty metod ....................................................................................................... 12 
Odwołanie this ............................................................................................................ 14 

V.  PrzeciąŜanie metod ................................................................................................. 15 

Obiekt jako argument.................................................................................................. 15 
Overloading ................................................................................................................ 17 

VI. 

Sposoby przekazywania argumentów................................................................. 19 

VII. 

Dynamiczne obiekty ........................................................................................... 21 

Inicjalizacja pól........................................................................................................... 22 
Konstruktor ................................................................................................................. 23 
Destruktor ................................................................................................................... 24 

Zadanie VII-1.......................................................................................................... 25 
Zadanie VII-2.......................................................................................................... 25 
Zadanie VII-3.......................................................................................................... 26 
Zadanie VII-4.......................................................................................................... 26 

VIII.  Konstruktory ....................................................................................................... 26 

Argumenty konstruktorów.......................................................................................... 26 
Konstruktor kopiujący ................................................................................................ 28 
Konstruktor kopiujący i pola wskaźnikowe................................................................ 29 

Zadanie VIII-1 ........................................................................................................ 29 

IX. 

Składowe statyczne............................................................................................. 33 

Pola statyczne ............................................................................................................. 33 
Metody statyczne ........................................................................................................ 35 
Dostęp do pól i metod ................................................................................................. 35 
Dostęp do pól i metod – c.d. ....................................................................................... 37 

Zadanie IX-1 ........................................................................................................... 38 
Zadanie IX-2 ........................................................................................................... 38 
Zadanie IX-3 ........................................................................................................... 38 

X.  Dziedziczenie.......................................................................................................... 39 
XI. 

Dostęp do składowych klasy............................................................................... 44 

Składowe publiczne .................................................................................................... 44 
Składowe prywatne..................................................................................................... 44 
Składowe chronione.................................................................................................... 44 

XII. 

Modyfikatory i dziedziczenie ............................................................................. 46 

Praktyczny cel stosowania modyfikatorów ............................................................ 47 
Reguły budowania klas potomnych ........................................................................ 48 
Zadanie XII-1.......................................................................................................... 49 

background image

66 

C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. II. 

______________________________________________________________________ 

______________________________________________________________________ 
 

©2006 Jerzy Kluczewski 

 

XIII.  Przesłanianie składowych klasy.......................................................................... 49 
XIV. 

Prosta hierarchia klas ...................................................................................... 50 

XV. 

Literatura pomocnicza ........................................................................................ 52 

XVI. 

Odpowiedzi do zadań...................................................................................... 53 

Zadanie VII-1.......................................................................................................... 53 
Zadanie VII-2.......................................................................................................... 54 
Zadanie VII-3.......................................................................................................... 55 
Zadanie VII-4.......................................................................................................... 56 
Zadanie IX-1 ........................................................................................................... 58 
Zadanie IX-2 ........................................................................................................... 59 
Zadanie IX-3 ........................................................................................................... 61 
Zadanie XII-1.......................................................................................................... 62