background image

Typy programowania 

• Strukturalne - wykorzystanie procedur i 

dopasowanie do nich sposobu reprezentacji 
danych 

 

• Obiektowe - to dane potrzebne do opisania 

obiektu i operacje opisujące interakcje 
użytkownika z obiektem 

background image

Typ jest przypisaniem rzeczy i zjawisk do określonych kategorii. 
• np. typ wartości całkowitych int pozwala na wykonywanie 

obliczeń arytmetycznych  
 

Typ zawiera informacje o:  

- rozmiarze zajmowanym w pamięci 

- rodzaju przechowywanej informacji 

- możliwych do wykonania operacjach 

Pojęcie typu 

background image

Pojęcie klasy 

Nowy typ jest tworzony poprzez zadeklarowanie klasy: 

 

class Pies 

public: 

 

unsigned int jegoWiek; 

 

 //zmienna 

 

 

unsigned int jegoWaga; 

 

 //zmienna 

 

void szczekaj(); 

 

 

//metoda czyli funkcja 

}; 

 
Deklaracja nie rezerwuje pamięci, ale informuje o rozmiarze 

każdego nowego Psa.  

background image

Pojęcie  obiektu 

Obiekt nowego typu jest tworzony tak jak zmienna: 

 

Pies Gere; 

 

 

 //obiekt 

Gere.jegoWiek = 8; 

Gere.szczekaj(); 

 
Przypisanie jest skuteczne, jeśli zmienna lub wywoływana metoda są 

typu public.  

Przypisanie jest nieskuteczne, jeśli zmienna lub wywoływana 

metoda są typu private (brak deklaracji typu public stanowi 
wskazanie typu private).  

 

background image

Implementacja metod 

void Pies::szczekaj(); 

 

std::cout << ”Hau  hau\n”; 

 

int Pies::pobierzWiek(); 

 

return jegoWiek; 

 

int Pies::pobierzWage(); 

 

return jegoWaga; 

 

background image

Przykładowy program zasadniczy 

#include <iostream> 

//using (

namespace std

) std::cout;  

/użyjemy samo polecenie  -  

cout 

int main() 

 

Pies Gere; 

 

 

 //obiekt 

 

Gere.jegoWiek = 8; 

 

Gere.jegoWaga = 48; 

 

std::cout << ”Gere jest psem, który w wieku  ” ; 

 

 std::cout <<  Gere.pobierzWiek() << ”lat, waży  ” ; 

 

 std::cout <<  Gere.pobierzWage() << ”kg.\n” ;  

 

Gere.szczekaj(); 

 

return 0; 

}; 

 

background image

Konstruktory 

Konstruktor jest specjalną metodą klasy. Ma taka samą nazwę jak 
klasa.  
Nie można podać typu wyniku konstruktora. Nie można przekazać z 
niego wyniku instrukcją return.  
Można w nim wywoływać funkcje składowe klasy. Można go 
wywołać jedynie przy tworzeniu nowego obiektu danej klasy. W klasie 
można (i zwykle tak sie robi) zdefiniować wiele konstruktorów. 
Konstruktor może mieć (nie musi) parametry. Konstruktor jest 
odpowiedzialny za dwie rzeczy: 

- zapewnienie, że obiekt będzie miał przydzieloną pamięć (to jest 
sprawa kompilatora), 

- inicjację obiektu (to nasze zadanie, realizuje je treść konstruktora). 

background image

Rodzaje konstruktorów 

1/ Konstruktor bezargumentowy: 

- można go wywołać bez argumentów, 

- jest konieczny, jeśli chcemy mieć tablice obiektów tej klasy. 

2/ Konstruktor domyślny: 

-  jeśli  nie  zdefiniujemy  żadnego  konstruktora,  to  kompilator  sam 
wygeneruje konstruktor domyślny (bezargumentowy), 

- ten konstruktor nie inicjuje składowych typów prostych, 

-  dla  składowych  będących  klasami  lub  strukturami  wywołuje  ich 
konstruktory bezargumentowe, 

-  jeśli  składowa  będąca  klasą  lub  strukturą  nie  ma  konstruktora 
bezargumentowego 

bądź  jest  on  niedostępny,  generowanie 

konstruktora domyślnego kończy sie błędem kompilacji. 

 

 

background image

Rodzaje konstruktorów cd.. 

3/ Konstruktor kopiujący: 

-  można  go  wywołać  z  jednym  argumentem  tej  samej  klasy, 
przekazywanym przez referencje,  

-  jeśli  żadnego  takiego  konstruktora  nie  zdefiniujemy,  to  kompilator 
wygeneruje go automatycznie. 

Uwaga:  automatycznie  wygenerowany  konstruktor  kopiujący  kopiuje 
obiekt  składową  po  składowej,  wiec  zwykle  się  nie  nadaje  dla 
obiektów zawierających wskaźniki(!)        
-  jest  wywoływany  niejawnie  przy  przekazywaniu  parametrów  do 
funkcji i przy przekazywaniu wyników funkcji(!) 

 

background image

Konstruktory cd.. 

Przykładowy konstruktor: 

Pies::Pies(int Wiek); 

 

 

 //konstruktor klasy Pies 

{  jegoWiek = Wiek; 

 

Pies::Pies();   

 

 

 

//konstruktor domyślny 

{  jegoWiek = 0; 

 

Pies::Pies(int &Pies Gere);   

 

//konstruktor kopiujący 

{  jegoWiek = Gere; } 

 
Konstruktor (jak i destruktor) należy zadeklarować typu public. 
  

 

background image

Tworzenie obiektów 

Użycie konstruktora: 
 

Pies Gere(5); 

Pies Gere = Pies(5); 

Pies *Czuka = new Pies(3); 

Pies &Gere_ref = Gere; 

        //utworzenie referencji do obiektu 

 

Pies Gere; 

 

 

background image

Referencja 

Referencja jest alternatywną nazwą zmiennej lub obiektu: 

int rats;  

 

 

int &rodents = rats; 

 

 //rodents to referencja, obie zmienne mają tę 

 

 

 

 

//samą wartość i adres 

int *prats = &rats; 

 

 //prats to wskaźnik 

*prats = 5; 

 

 

 // (=rats) jest to dereferencja 

Referencja  podobna  jest  wskaźnikowi,  ale  używana  jest  jako 

parametr  formalny  funkcji,  co  powoduje,  iż  funkcja  działa  na 
danych  oryginalnych,  a  nie  na  kopii.  Pozwala  to  na 
modyfikowanie wartości więcej niż jednej zmiennej. 

int refcube(int &ra) 

{  ra *= ra * ra; 

  return ra;     } 

 

background image

Destruktor 

Gdy  obiekt  kończy  swoje  istnienie  automatycznie  zwalnia  się 
zajmowana przez niego pamięć. Nie dotyczy to jednak zasobów, które 
obiekt sam sobie przydzielił w czasie swego istnienia. 

Ten cel realizuje destruktor, będący metodą klasy. Klasa może mieć co 
najwyżej jeden destruktor. Destruktor nie ma parametrów. Nie można 
specyfikować  typu  wyniku  destruktora.  Nie  można  w  nim  używać 
instrukcji return z parametrem.  

Nazwa destruktora jest taka sama jak nazwa klasy, tyle że poprzedzona 
tyldą: 
Pies::~ Pies(); 


// jeśli nie ma żadnych zasobów do zwolnienia 

 

background image

Destruktor cd.. 

 

Destruktor jest odpowiedzialny za dwa problemy: 

-  zwolnienie  pamięci  zajmowanej  przez  obiekt  (to  sprawa 
kompilatora), 

-  zwolnienie  zasobów  (to  nasze  zadanie,  zwalnianie  zasobów 
zapisujemy jako treść destruktora). 

 

Destruktor  wywołuje  sam  kompilator.  Jeśli  nie  utworzy  go 
programista w definicji klasy, to kompilator zrobi to niejawnie. 

 

  

 

background image

Wskaźniki 

Przykłady użycia wskaźników: 

int  *ptr; 

int*  ptr; 

int*  p1,  p2;   

 

//p2 nie jest wskaźnikiem, więc czym? 

 

double *  ptr; 

char *  ptr; 

 

long *  fellow = 223344; 

  

//niepoprawne, brak przypisan.  

int *  ptr  =  (int*) 0xB800000;  

 //poprawne  

 

 

  

background image

Przeciążanie operatorów 

Ten sam symbol ma kilka znaczeń i kompilator wybiera jedno z nich 

na podstawie kontekstu: 

 

dotyczy to np.: <<,  *,  &,   

  / (dzielenie różnych typów liczb),  

  -  (odejmowanie, negacja ); 

 

 

 

  

 

background image

Dziedziczenie 

Użycie klasy bazowej do utworzenia kolejnej (własnej) stanowi 

proces dziedziczenia.  

 
Użycie więcej niż jednej klasy bazowej do utworzenia kolejnej 

(własnej) stanowi proces dziedziczenia wielokrotnego

 

Class Student : private std::string,  private std::vallarray<double> 

Public: 

 

… 

}; 

 

 

  

background image

Rekurencja 

Wywołanie przez funkcję samej siebie stanowi rekurencję.  
#include <iostream

void countdown (int n); 

int main() 

{   countdown (4); 

  return 0;  } 

void countdown (int n); 

{  using namespace std;

 

 

  cout << ”Odliczanie …” << n << endl; 

  if (n>0) 

 countdown (n-1); 

 

//wywołanie samej siebie 

  cout << n << ”.    Zstępowanie. \n” ; 

};