Koncepcja programowania obiektowego

Otaczający nas świat to róznego rodzaju przedmioty. Tworząc program komputerowy dokonujemy pewnego ich odwzorowania. Krokiem do integracji opisu przedmiotów i metod określających jego właściwości jest przejście z programowania proceduralnego do programowania obiektowego. W programowaniu proceduralnym funkcje i zmienne opisujące dany przedmiot nie były ze sobą powiązane. W przypadku programowania zorientowanego na obiekt (programowania obiektowego) dokonuje się powiązania metod (funkcji programu) z danymi (zmiennymi) definiującymi przedmiot. Wszystko to grupuje się w tzw. klasie zawierającej zarówno dane definiowanego przedmiotu, jak i funkcje. W ten sposób definicje przedmiotu i jego właściwości znajdują się w jednym miejscu. W języku C++, opis klasy jest dokonywany za pomocą pól (zmienne) i metod(funkcje).

Definicja klasy

Definicja klasy zawiera dwie części: nagłówka składającego się ze słowa kluczowego class, po którym następuje nazwa klasy oraz z ciała klasy ograniczonego parą nawiasów klamrowych i zakończonego średnikiem.
class TPunkt
{

}; 
Została zdefiniowana klasa TPunkt. Jest to pewnego rodzaju przepis na tworzenie obiektów. Można to przyrównać do przepisów kulinarnych. Klasa to przepis na ulubione ciasto, a obiekt to już gotowe ciasto stworzone na podstawie naszego przepisu (klasy).

Uwaga! Definicja klasy musi zawsze kończyć się średnikiem.

Wewnątrz ciała klasy deklaruje się składniki klasy. Składnikami klasy mogą być różnego rodzaju typy danych nazywane polami (są to dobrze znane zmennne).
class TPunkt
{
 public: //sekcja publik zostanie wyjaśniona później.
  int x;   //pole typu int o nazwie x
  int y;   //pole typu int o nazwie y  
}; 
Tak więc nasza klasa wzbogaciła się o dwa pola.

Aby zadeklarować metodę należy ją także dopisać do ciała klasy w postaci funkcji.
class TPunkt
{
 public:
  int x;   
  int y;  
  void fun(void){ } //definicja funkcji fun() w klasie
}; 
W klasie zadeklarowano metodę (funkcję) o nazwie fun. Definicja funkcji znajduje się pomiędzy nawiasami klamrowymi. W przypadku, gdy definicja funkcji jest obszerna można ją przenieść poza klasę.
class TPunkt
{
 public:
  int x;   
  int y;  
  void fun(void); //deklaracja funkcji fun()
}; 

void TPunkt::fun()
{
	//definicja funkcji fun() poza klasą
}
W ten oto sposób możemy sprawić, że ciało klasy będzie zawierało tylko deklaracje funkcji, a ich definicje będą znajdowały się w innym miejscu (lub nawet w innym pliku źródłowym).
Aby jednoznacznie określiś która funkcja należy do określonej klasy stosuje się identyfikator dostępu :: podając
void nazwa_klasy :: nazwa_funkcji(void)
{
  //definicja funkcji 
}

Hermetyzacja

Wewnątrz ciała klasy znajdują się pola i metody. Część pól i metod można odpowiednio ukryć przed "zewnętrznym światem" klasy tak jak to ma miejsce z przedmiotami ze świata rzeczywistego. Nie potrzebna jest nam znajomość wewnętrznej budowy do ich codziennej obsługi. Mamy dostęp tylko do wybranych metod. W ten sposób część danych i funkcji jest przed nami ukryta. Tak samo jest w programowaniu obiektowym.
W ciele klasy deklaruje się odpowiednie sekcje: public widoczną globalnie, protected widoczną w obiektach podklasy oraz private widoczną tylko dla danego obiektu.
class TPunkt
{
  public:

  private:  

  protected:

};
Sekcja działa na takiej zasadzie, że dotyczy występujących po niej metod i pól. Liczba deklarowanych sekcji jest dowolna. Od chwili zadeklarowania nowej sekcji występujące po niej metowy i pola będą odpowiednio udostępniane z nową sekcją. W przypadku braku deklaracji sekcji domyślnie jest przypisana sekcja prywatna.
class TPunkt
{
   fun1(){}  

  public:
 
   fun2(){}
   fun3(){}
   
  private:

   fun4(){}
   int x;
   int y;

  public:

   fun5(){}
};
W tym przykładzie metody: fun2(), fun3() i fun5() są publiczne, a metody fun1(), fun4() oraz pola x i y są prywatne
Główną zaletą hermetyzacj (enkapsulacji lub kapsułkowania) jest ochrona pól obiektów klasy przed dostępem z zewnątrz. Można tak zaprojektować klasę, że dostęp do pól obiektu będzie realizowany tylko przez odpowiednie funkcje.
class TPunkt
{
  private:
   int x;
   int y;
  public:
   int getx(){return x;}
   int gety(){return y;}
   void putx(int xx){x=xx;}
   void puty(int yy){y=yy;}
};
Funkcje getx(), gety(), putx() i puty() znajdują się w sekcji public i są widoczne poza obiektem klasy. Pola x i y nie są widoczne poza obiektem klasy, ale jedynie wewnątrz obiektu (mają do niej dostęp metody klasy, czyli nasze funkcje getx(), gety(), putx() i puty()). Z tego względu te funkcje stanowią "interfejs" dostępu do pól obiektu klasy TPunkt. Daje to nam kontrolę nad wprowadzaniem i odczytem pól x i y poprzez odpowiednie definicje metod.

Tworzenie obiektów

To co było do tej pory napisane odnosiło się do klasy, czyli naszego przepisu na stworzenie obiektu. Sam proces tworzenia obiektu nazywamy instancjonowaniem lub konkretyzacją klasy.

Tworzenie obiektów dokonuje się tak samo jak tworzenie zmiennych. np.
//nazwa_klasy nazwa_instancji
int i;             //zmienna typu int o nazwie i
TPunkt p1;	   //obiekt klasy TPunkt o nazwie p1
Do obiektów odwołujemy się poprzez kropkę lub poprzez -> np.:
class TPunkt
{
   int x;
   int y;
  public:
   int kolor;
   void putx(int xx){x=xx;}
   void puty(int yy){y=yy;}
   void kolor(int kk){kolor=kk;}
};

main(void)
{
   TPunkt p1;  	//obiekt stworzony statycznie
   p1.kolor=10;   	//odwołanie do pola przez kropkę
   p1.putx(20);	//odwołanie do funkcji przez kropkę

   TPunkt *wsk;	//wsk - wskaznik na obiekt klasy TPunkt

    wsk = new TPunkt;	//operator new

   wsk->kolor=10;   	//odwołanie do pola przez ->
   wsk->putx(20);	//odwołanie do funkcji przez ->

   delete wsk;	//operator delete
}

Pola statyczne

Pola klasy mogą być zadeklarowane jako statyczne wewnątrz deklaracji klasy. Do tego celu stosuje się atrybut static. Tak zadeklarowane pole klasy jest współdzielone przez wszystkie obiekty danej klasy. Element static nie jest częścią obiektów danej klasy i deklaracja elementu statycznego w deklaracji klasy nie jest definicją. Taką definicję wprowadza się poza klasą.
class TPunkt
{
  private:
   int x;
   int y;
  public:

   static int a;	//definicja pola statycznego
}

int TPunkt::a = 1;	//deklaracja pola statycznego poza klasą TPunkt 

Odwołanie do takiego pola jest możliwe przez podanie nazwy klasy z operatorem zakresu :: lub przez operator . i ->.
 TPunkt::a = 2;         //odwołanie do pola statycznego przez ::

 TPunkt p1;
 p1.a =2; 		//odwołanie do pola statycznego przez .

 TPunkt *wsk;
 wsk = new TPunkt;
 wsk->a=10; 		//odwołanie do pola statycznego przez ->
 delete wsk;	
Dwa ostatnie sposoby (operator . i -> ) są takie same jak odwoływania do zwykłych pól niestatycznych.