beesoft.org

Klasy i struktury.

W tym rozdziale chiałbym przedstawić idee klas. Ideę, która odróżnia C++ od C tak, jak dzień różni się od nocy.

Dlaczego w jednym i tym samym rozdziale omawiam klasy i struktury razem?
Dlatego że w języku C++ to to samo. Wszystko co będę mówił o klasach dotyczy także struktur (i unii).
Słowa kluczowe class, struct można stosować wymiennie.
Dla osób znających C może się to wydawać dziwne, ale w C++ tak właśnie jest.
Istnieje pewna różnica, ale wspomnę o niej w odpowiednim momencie w dalszej części opisu.

W celu przybliżenia idei klasy pokaże jej tworzenie i użytkowanie na przykładzie klasy o nazwie Ulamek.
Klasa ta będzie abstrakcyjną reprezentację ułamków arytmetycznych.
Będzie ona jendocześnie nowym typem danych uznawanym przez kompilator (na równi z typami wbudowanymi).

Pierwsza implementacja.

Na początek, dla prostoty, nasze wymagania względem klasy Ulamek będą minimalne.
Chodzi o to, aby była ona jak najprostsza. Na początek wystarczy jak napisze na ekranie swoją wartość.
W kolejnych krokach będziemy dodawać kolejne operacje (np. działanie mnożenie ułamków).

Najpierw należy zadać sobie pytanie: co tak naprawdę reprezentuje obiekt zwany ułamkiem.
Odpowiedź na to pytanie będzie jednocześnie informacją z jakich komponentów składa się obiekt.
Każdy kto ukończył szkołe podstawową nie powinien mieć problemów z odpowiedzią.
Każdy ułamek składa się z dwóch liczb: dzielnej i dzielnika.
Jako ich reprezentację wykorzystamy typ wbudowany int. Tak więc ułamek tworzą dwa komponenty:

  1. liczba całkowita int będąca dzielną
  2. liczba całkowita int będąca dzielnikiem

UWAGA. Przez cały czas należy pamiętać, że:

  1. Ułamek składa się z dzielnej i dzielnika.
  2. Dzielnik NIE MOŻE być równy zeru (nie wolno dzielić przez zero).

Deklaracja klasy.

Najprostsza deklaracja klasy wygląda następująco:

class Ulamek {
	deklaracje_elementów_składowych_klasy
};

Pierwszą linię (class Ulamek) nazywamy nagłówkiem klasy (class head).

Deklaracje elementów składowych klasy to:

  1. deklaracja konstruktora(/ów) klasy,
  2. deklaracja destruktora klasy,
  3. deklaracje zmiennych klasy, zwanych składowymi lub atrybutami,
  4. deklaracje funkcji klasy, zwanych metodami,
  5. etykiety dostępu (member access specifier).

Deklaracja klasy zaczyna się zawsze słowem kluczowym (czyli zastrzeżonym słowem ze słownika C++) class.
Za słowem class należy napisać nazwę klasy (np. Ulamek).
Dalej następuje już deklaracja właściwa zawarta pomiędzy nawiasami klamrowymi ({ }).
Deklaracje klasy musi być zakończona średnikiem (;).

Należy pamietać, że zadeklarowana przez nas klasa staje się nowym typem. Kolejnym znanym kompilatorowi typem, oprócz znanych mu od początku typów wbudowanych (jak int, long, itd). Ten typ jest jednak typem zdefiniowanym przez użytkownika, czyli przez nas.
Gdy później w programie utworzymy zmienne typu naszej klasy to będziemy je nazywać obiektami lub instancjami.
Zbiór wszystkich wartości przypisanych składowym obiektu nazywamy stanem obiektu (state of the object).

Ułamek jako obiekt należy w pewnym momencie działania programu utworzyć i zniszczyć.
W tym celu istnieją specjalne quasi-funkcje nazwane odpowiednio: konstruktor i destruktor.
Konstruktor i destruktor różnią się od innych metod klasy tym że:

  1. Nie moga mieć dowolnej, wymyślonej przez użytkownika nazwy.
    Konstruktor musi nazywać się dokładnie tak jak klasa, która tworzy i której jest elementem (np. Ulamek).
    To samo dotyczy destruktora, z tym że musi się rozpoczynać znakiem tyldy (np. ~Ulamek).
  2. Ani konstruktor, ani destruktor nie zwrajaca żadnych wartości
    (należy o tym pamietać, gdyż wynikają z tego poważne konsekwencje).
  3. Nawet jak użytkownik nie napisze własnego konstruktora i destruktora, to i tak zostaną utworzone automatycznie na etapie kompilacji.
  4. Konstruktor i destruktor są wywoływane automatycznie w momencie tworzenia i niszczenia obiektu.

Zwyczajowo deklarację klasy umieszczamy w pliku nagłówkowym z rozszerzeniem .h (np. Ulamek.h).

Nasza początkowa deklaracja klasy Ulamek:

#ifndef INCLUDED_Ulamek_h
#define INCLUDED_Ulamek_h

#include <string>

// Klasa Ulamek

class Ulamek
{
// ******* KONSTRUKCJA / DESTRUKCJA *******
public:
	Ulamek();					// Tak zwany konstruktor domyślny (default constructor)
	Ulamek( int in_dzielna);			// Konstruktor ze wskazaną wartością dzielnej.
	Ulamek( int in_dzielna, int in_dzielnik );	// Konstruktor ze wskazanymi wartościami dzielnej i dzielnika.

// ******* SKŁADOWE *******
private:
	int d_dzielna;
	int d_dzielnik;

// ******* METODY *******
public:
	double      as_double();
	std::string as_string();
};

#endif // INCLUDED_Ulamek_h
Tak więc w języku klas dzielną i dzielnik nazywamy składowymi, wszystkie funkcje o nazwie Ulamek nazywamy konstruktorami, a funkcje as_double() oraz as_string() nazywamy metodami.

Etykiety dostępu

Etykiety dostępu to następujące słowa kluczowe private:, protected: i public: (proszę zwrócić uwagę na dwukropki).
Wszystkie składowe klasy znajdujące się poniżej słowa private: będą dostępne (będzie można je używać) tylko i wyłącznie wewnątrz klasy. Nie będa dostępne spoza klasy - można powiedzieć że na zewnątrz klasy nie będą widziane, jakby ich nie było, świat zewnętrzny nie ma pojęcia o ich istnieniu.

REGUŁA: wszystkie składowe klasy (zmienne) powinny zawsze być prywatne.
Oczywiście nie muszą. Może być tak, że wszystkie składowe będą publiczne.
Ale dobry styl programowania oznacza ukrycie wszystkich składowych jako prywatnych.

To co ma być dostępne na zewnątrz klasy musi być poprzedzone słowem kluczowym public.
Ewentualny dostęp do prywatnych składowych może się odbywać poprzez interfejs klasy (public interface).
Interfejs klasy to jej publiczne metody.
Słowo kluczowe protected ma znaczenie dopiero na etapie dziedziczenia klas. Jego znaczenie wytłumaczę w stosownym momecie. W przypadku jednej prostej klasy określenie dostępu jako protected ma dokładnie takie samo działanie jak private.

Klasy a struktury

Pojawia się pytanie: a co będzie jak zapomisz podać jakąkolwiek etykiete dostępu.
Otóż w przypadku klasy wszystkie jej elementy będą prywatne
Tylko to odróżnia klasę od struktury.
W przypadku struktury wszystkie jej elementy będą publiczne.

Contact: piotr@beesoft.org
(C) 2006-2008 beesoft.org
Last modification date: 2008-06-29
Visitis counter:
counter of visits