Programozás II. 4. Dr. Iványi Péter 1
inline függvények Bizonyos függvények annyira rövidek, hogy nem biztos hogy a fordító függvényhívást fordít, hanem inkább az adott sorba beilleszti a kódot. #include <iostream> using namespace std; #include <iostream> using namespace std; inline int max(int a, int b) return ((a > b)? a : b); int main() cout << max(10,20); return 0; int main() cout << ((10 > 20)? 10 : 20); return 0; 2
inline függvények inline esetén nincs verem művelete Paraméter átadás, visszatérési érték Növeli a kód méretét, hiszen sok az ismétlés Csak kis méretű kódot érdemes beilleszteni Csak egy kérés, a fordító nem biztos hogy megteszi Osztályok esetén eddig is ezt használtuk Gyorsabb kód, de a használó látja mi történik Csak a nagyon kicsi, legbiztosabb részeket érdemes inlineolni 3
static kulcsszó C-ben #include <stdio.h> int osszegez(int a) static int allapot = 0; allapot += a; return allapot; int main() osszegez(1); osszegez(2); printf( %d, osszegez(3)); return 0; 6 4
#include <iostream> using namespace std; class osztott static int a; int b; public: void set(int i, int j) a=i; b=j; void show() cout << "Static: " << a << "nem static: " << b << endl; ; int osztott::a = 0; int main () osztott x, y; x.set(1,1); x.show(); y.set(2,2); y.show(); x.show(); return 0; Static: 1 nem static: 1 Static: 2 nem static: 2 Static: 2 nem static: 1 5
static kulcsszó Az osztályon belül csak deklaráljuk, de mivel több osztály is megosztja ezért a konkrét definíció osztályon kívül kell legyen, a globális értelmezési tartományban Hivatkozni lehet rá: Mint konkrét objektum elemeként: cout << a.n Mint osztály részeként: cout << szam.n Ezek tulajdonképpen globális változók!!! 6
#include <iostream> using namespace std; class osztott public: static int a; ; static kulcsszó Többféle hivatkozás int osztott::a = 0; int main () osztott::a = 99; cout << "A értéke:" << osztott::a << endl; osztott x; cout << "A értéke:" << x.a << endl; return 0; 7
using namespace std; #define FOGLALT 1 #define SZABAD 0 class valami static int eroforras; public: int get_res() if(eroforras) return 0; else eroforras=foglalt; return 1; void free_res() eroforras=szabad; ; int valami::eroforras=0; int main () valami a, b; static kulcsszó Erőforrás kontrol, egyszerre csak egy objektum használja if(a.get_res()) cout << "Megvan\n"; else cout << "Nincs\n"; if(b.get_res()) cout << "Megvan\n"; else cout << "Nincs\n"; a.free_res(); if(b.get_res()) cout << "Megvan\n"; else cout << "Nincs\n"; return 0; Megvan Nincs Megvan 8
#include <iostream> using namespace std; class szam public: static int n; szam () n++; ; ~szam () n--; ; ; int szam::n=0; static kulcsszó Hány darab objektum létezik void f() szam a; cout << szam::n << endl; // 7 int main () szam a; szam b[5]; cout << szam::n << endl; // 6 f(); cout << szam::n << endl; // 6 return 0; 9
Barátok, friend Lehetőség van arra, hogy egy olyan függvény férjen hozzá egy osztály privát változóihoz, amley nem tagfüggvénye az osztálynak friend függvények Hol használjuk: Operátor overloading esetén Bizonyos I/O esetén 10
#include <iostream> using namespace std; class valami int a, b; public: friend int sum(valami x); void set_ab(int i, int j) a=i; b=j; ; int sum(valami x) // a függvény nem része az osztálynak!!!! return(x.a + x.b); void main() valami n; n.set_ab(2,3); cout << sum(n) << endl; 11
Két különböző osztály Friend függvények Mind a kettő megjelenít egy üzenet ablakot A program többi tudni szeretné hogy látható-e egy ablak, mert akkor nem üzennek 12
#include <iostream> using namespace std; #define SZABAD 0 #define FOGLALT 1 class C1; class C1 int status;... public: void set_status(int s) status=s; friend int szabad(c1 a, C2 b); ; class C2 int status;... public: void set_status(int s) status=s; friend int szabad(c1 a, C2 b); ; 13
int idle(c1 a, C2 b) if(a.status b.status) return 0; else return 1; void main() C1 x; C2 y; x.set_status(szabad); y.set_status(szabad);... if(idle(x,y))... x.set_status(foglalt); 14
Friend függvények Az egyik osztály függvénye lehet friend függvénye egy másik osztálynak Egy osztály is lehet barátja egy másik osztálynak A friend osztály minden privát változóhoz hozzáfér!! 15
Objektumok Egymáshoz rendelhetők, értékadás Lehetnek függvények visszatérési értékei Lehetnek függvények argumentumai 16
Egy furcsaság Objektumokat egyszerűen át lehet adni függvényeknek, de... 17
#include <iostream> using namespace std; class valami int a; public: valami(int n) a=n; cout << "Konstruktor " << a << endl; ~valami() cout << "Destruktor " << a << endl; void set_a(int n) a=n; int get_a() return a; ; 18
void f(valami o) o.set_a(2); cout << "Lokalis a: " << o.get_a() << endl; void main() valami ob(1); f(ob); cout << "in main a: " << ob.get_a() << endl; 19
Az eredmény Konstruktor 1 Lokalis a: 2 Destruktor 2 in main a: 1 Destruktor 1 innen hiányzik egy konstruktor Amikor argumentumként adjuk át az objektumot a normális konstruktor nem hívódik meg, helyette egy másoló konstruktor hívódik meg. (Erről egy kicsit később lesz szó.) 20
#include <iostream> using namespace std; class valami int a; public: void set_a(int n) a=n; int get_a() return a; ; void main() valami o; o = f(); cout << o.get_a() << endl; Bitenkénti másolás valami f() valami x; x.set_a(1); return x; Függvény visszatérési értéke is lehet objektum 21
Objektumok értékadásban #include <iostream> using namespace std; class valami int a; public: void set_a(int n) a=n; int get_a() return a; ; void main() valami ob1, ob2; ob1.set_a(2); ob2 = ob1; cout << ob2.get_a() << endl; Bitenkénti másolás 22
Másoló konstruktor Alap esetben bitenként másol Nincs is gond amíg nem egy pointert másol le Emlékezzünk minden objektumnak külön adatai vannak A többiegy kicsit később 23
Objektum tömbök Objektumokból is lehet tömböt készíteni Szintaxis ugyanaz! Egy paraméteres konstruktor esetén mint C-ben, egyébként csak a konstruktor meghívásával lehet inicializálni 24
#include <iostream> using namespace std; class valami int a; public: void set_a(int n) a=n; int get_a() return a; ; void main() valami ob[3]; int j; for(j=0;j<3;j++) ob[j].set_a(j+1); for(j=0;j<3;j++) cout << ob[j].get_a() << endl; 25
#include <iostream> using namespace std; class valami int a; public: valami(int n) a=n; int get_a() return a; ; void main() valami ob[3] = 1,2,3; int j; for(j=0;j<3;j++) cout << ob[j].get_a() << endl; 26
#include <iostream> using namespace std; class valami int a; public: valami(int n) a=n; int get_a() return a; ; void main() valami ob[3] = valami(1), valami(2), valami(3); int j; for(j=0;j<3;j++) cout << ob[j].get_a() << endl; 27
#include <iostream> using namespace std; class valami int a; public: valami(int n) a=n; int get_a() return a; ; void main() valami a[4]; // érvénytelen int j; for(j=0;j<3;j++) cout << ob[j].get_a() << endl; 28
#include <iostream> using namespace std; class valami int a; public: valami(int n) a=n; valami() a=0; int get_a() return a; ; void main() valami a[4]; // érvényes!!! int j; for(j=0;j<3;j++) cout << ob[j].get_a() << endl; 29
Fortran-ban: C-ben: int tomb[1000]; malloc, free C++ -ban: Memória kezelés new, delete operátorok Több előnye is van az új operátoroknak 30
new és delete new: lefoglalja a memóriát és visszaad egy mutatót, mely a területre mutat Ha nincs elég memória kivételt dob (erről később) delete: felszabadítja a lefoglalt memóriát Csak a new-al foglalt memóriánál használjuk p_var = new típus;... delete p_var; 31
Előnyök: new és delete Nem kell megmondani a lefoglallandó objektum méretét sizeof operátor nem kell, nem is hibázhatunk Mindig a megfelelő típusú mutatót adja vissza nem kell cast-olni void *malloc(int size); Mindkettő felüldefiniálható 32
#include <iostream> using namespace std; void main() int *p; // a memória inicializálása p = new int (87); cout << *p << endl; delete p; 33
Tömb lefoglalása p_var = new tömb_típus [méret];... delete [] p_var; Tömböket nem lehet inicializálni!!!!! 34
#include <iostream> using namespace std; void main() int *p, j; // a memória inicializálása p = new int [10]; for(j=0; j < 10; j++) p[j] = j; for(j=0; j < 10; j++) cout << p[j] << " "; delete [] p; 35
Dinamikus objektumok A new és delete segítségével objektumokat is lehet dinamikusan kezelni!!! 36
#include <iostream> #include <string> using namespace std; class szamla double ertek; string nev; public: void set(double e, string n) ertek=e; nev=n; double get_ertek() return ertek; string get_nev() return nev; ; void main() szamla *p; p = new szamla; p->set(1234.56, "Kovacs Istvan"); cout << p->get_nev() << " " << p->get_ertek() << endl; delete p; 37
#include <iostream> #include <string> using namespace std; class szamla double ertek; string nev; public: szamla(double e, string n) ertek=e; nev=n; double get_ertek() return ertek; string get_nev() return nev; ; void main() szamla *p; p = new szamla(1234.56, "Kovacs Istvan"); cout << p->get_nev() << " " << p->get_ertek() << endl; delete p; 38
#include <iostream> #include <string> using namespace std; Dinamikus objektum tömb esetén kell egy paraméter nélküli konstruktor class szamla double ertek; string nev; public: szamla() ertek=0; nev="ismeretlen"; szamla(double e, string n) ertek=e; nev=n; void set(double e, string n) ertek=e; nev=n; double get_ertek() return ertek; string get_nev() return nev; ; 39
void main() szamla *p; int j; p = new szamla[3]; for(j = 0; j < 3; j++) cout << p[j].get_nev() << " " << p[j].get_ertek() << endl; p[0].set(1111, "Alma Rozsa"); p[1].set(2222, "Korte Bela"); p[2].set(3333, "Szilva janos"); for(j = 0; j < 3; j++) Paraméter nélküli konstruktort hívja meg cout << p[j].get_nev() << " " << p[j].get_ertek() << endl; delete [] p; 40