Wednesday, May 18, 2011

3.3 - Konstruktor es Destruktor

Egy osztaly konstruktorai harom kategoria sorolhatok

- alapertelmezett(implicit)
- masolo(copy)
- mas konstruktor

3.2 - Statikus tagok

Az alabbi pelda szemlelteti a statikus tagok deklaraciojat, definiciojat es hasznalatat.

#include 
using namespace std;

class InstanceCounter{
 private:
  static int counter; //Deklaracio
  int i;
 public:
  InstanceCounter(int _i=0) : i(_i){counter++;}
  ~InstanceCounter(){counter--;}
  static int getCounter(){return counter;}
};

int InstanceCounter::counter=0; //Definico

int main(){
 cout<<"Peldanyszam" << InstanceCounter::getCounter() << endl;
 InstanceCounter o1 o2 o3;
 cout<<"Peldanyszam" << InstanceCounter::getCounter() << endl;
 InstanceCounter * p = new InstanceCounter(10);
 cout<<"Peldanyszam" << InstanceCounter::getCounter() << endl;
 delete p;
 cout<<"Peldanyszam" << InstanceCounter::getCounter() << endl;
 return 0;
}

3.1 - Implicit parameterek

Pelda:
Datum(int ev=0,int ho=0, int nap=0){
// stb
}

3.0 - Osztalyok es Objektumok

Minden programozas nylev rendelkezik egy alapertelmezett tipushalmazzal es lehetoseget biztosit ennek felhasznaloi tipusok altali kiterjesztesere.
C nyelvben felhasznaloi tipust a struct  kulcsszoval vezethettunk be.
C++ nyelvben a struktura tipus is atalakul, nemcsak adattagokat, hanem metodusokat is tartalmazhat. Az osztalydeklaracio a class  kulcsszot es az osztalynevet tartalmazza. Pelda: class Alma;
Az osztalydefiniciot 2 forrasallomanyba szokas elhejezni. A fejallomanyban (.h) az osztaly definicio, az adattagokat illetve a metodus deklaraciokat tartalmazza es a metodusok definicioit egy C++ forrasfajlban szokas elhelyezni, ugy ahogyan a Stack modul eseteben is tetunk.
Pelda: datum.h
class Datum{
 private:
  int ev, ho, nap;
 public:
  Datum(int _ev, int _ho, int _nap);
};

Egy osztaly tagjai haromfele lathatosaguak lehetnek
- privat (private)
- vedett (protected)
- nyilvanos (public)

2.6 - Kivetelkezeles

Ma mar minden programozasi nyelvben jelen van. Tulajdonkeppen egyfele hibakezelez altalanositasanak is tekintheto.
Olyan hibakat oldhatunk meg vele, amit helyben nem lehet megszuntetni.
Egyik nagy elonye , hogy a hagyomanyos kodot es a hibakezelo kodot szetvalassza.
A C++ nylevben a kiveltelesemenyt jelenzni lehet egy primitiv tipusu valtozo segitsegevel.
class Error{...};
void f(){
   if(feltetel){
     throw Error()
   }
}

// kivetel lekezelese

try{
   f();
}catch(Error){
 // kiveltelkezelo blokk
}
Pelda: stack.h
#ifndef stack_h
#define stack_h
using namespace std;
 class Staxk{
  public:
   class Stack_Overflow{};
   class Stack_Underflow{};
   virtual void push(char)=0;
   virtual char pop()=0;

 };

 class Array_Stack : public Stack{
  private:
   char *s;
   int top;
   int max_size;
  public: 
   Array_Stack(int max_size);
   Array_Stack(const Array_Stack&);
   ~Array_Stack();
   void push(char c) throw (Stack_Overflow);
   char pop() throw (Stack_Underflow); 
 };
$endif

A fenti Stack osztaly egy absztrakt osztaly amely csak tipusdefiniciokat es fugvenydeklaraciokat tartalmaz, tehat tamogatja az absztrak adatipusokat, mivel nem ad meg semmi informaciot az adatok abrazolasara, illetve a muveletek implementaciojara vonatkozoan.
Az ilyen absztrakot osztalyokat feluleteknek is nevezzuk, mert feluletet biztositnak mas osztalyok szamara.
Erre epitjuk fel az Array_Stack konkrek osztalyt, amely az absztrakt osztaly konkret leszarmazotja lesz.
Az osztalyunknak ket konstruktora van az elso parameter nelkuli, a masodik a masolo konstruktor.
A C++ nincs automatikus szemetgyujtes ezert szuksegunk van a destruktorra, amely az objektum dinamikus helyfoglalasat semmisiti meg.

Pelad: stack.cpp

#include "stack.h"
#include 
using namespace std;

Array_Stack :: Array_Stack(int _max_size){
 max_size = _max_size;
 s = new char[_max_size];
 top = 0;
}

// masolo konstruktor
Array_Stack :: Array_Stack(Array_Stack & _as){
 this->max_size = _as.max_size;
 this->s = new char[max_size];
 this->top = _as.top;
}

// destruktor
Array_Stack :: ~Array_Stack(){
 //cout<<"\nDestructor: "<< this->max_size<<"\n";
 delete [] s;
}

void Array_Stack :: push(char c) throw (Stack_Overflow){
 if(top >= max_size) throw Stack_Overflow();
 s [top++] = c;
}

char Array_Stack :: pop() throw (Stack_Underflow){
 if(top == 0) throw Stack_Underflow();
 return s[--top];
}


A fenti kod a Stack_Array osztaly metodusait implementalja.
Pelda: test_stack.cpp
#include 
#include "stack.h"
#include 
using namespace std;

int main(){
 Array_Stack as(100);
 try{
  printf("\n%c", as.pop());
 }catch(Stack :: Stack_Underflow x){
  //cout<<"Stack_Underflow"<<"\n";
 }
 return 0;
}

2.5 - Dinamikus helyfoglalas

A dinamikus helyfoglalas futas kozben tortenik a memoria heap (halom) szegmenseben.
A valtozok kezelese ebben az esetben a programozo felelossege, a helyfoglalast a new , new[] operatorok vegzik mig a felszabaditast a delete, delete[] operatorok.

Pl:
int *a = new int; // helyfoglalas egyetlen egesz szamnak
*a = 10;
delete a; // felszabaditas

int *t = new int[10] // helyfoglalas egy 10 elemu egesz szamokbol allo tombnek
for(int i=0; i<10; i++)
   t[i]=10;
delete [] t; //felszabaditas

Van egy Datum osztalyunk, keszitsunk belole peldanyokat.
Datum *d = new Datum();
delete d;

// ebben az esetben kotelezo hogy letezen a Datum osztalyunknak
// parameter nelkuli konstruktora
Datum *td = new Datum[10];
delete [] td;

// a masodik megoldas letrehozni egy mutato tombot
// es abban egyenkent inicializalni az elemeket
int i;
Datum **d = new Datum *[10];
for(i=0; i<10; i++)
   d[i] = new Datum(2005,10,i+1);

for(i=0; i<10; i++)
   delete d[i];

delete [] d;