Programozás alapjai II. (2. ea) C++ C++ kialakulása, nem OOP újdonságok: Szeberényi Imre BME IIT
<
[email protected]>
MŰEGYTEM 1782 C++ programozási nyelv
© BME-IIT Sz.I.
2011.02.15.
-1-
C++ kialakulása Veszélyforrások csökkentése
Objektum orientált szemlélet
C+ javítások
OOP elemek
C++ Javítások egy része átkerült az ANSI C-be. C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
-2-
C és C++ viszonya
preprocesszor buta C C könyvtár
C++ programozási nyelv © BME-IIT Sz.I.
preprocesszor okos C C könyvtár
C++ könyvtár
2011.02.15.
-3-
C és C++változatai C++ C w. classes
1972
1979
1978
C++98 1985
1983
1990
1998
1989
C K&R C
2010
2003
2007
1999
C90
C++0x
C++03
C99 C1X
ANSI C
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
-4-
C99 • változók és a kód keverése (for fejében is) for (int i = 1; i < 12; i++) ….
• // comment, const, enum, inline • változó hosszúságú tömb (függvényben) void f(int b) { int c[b]; // változó méretű tömb }
• új típusok (pl. long long, double _Complex) • Pontosabb specifikáció pl: -3/5 = 0 -3%5= -3 // C89-ben lehetne -1 és +2 C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
-5-
C99 támogatottság
Wikipedia alapján C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
-6-
Általános kódolási tanácsok • Olvasható legyen a kód, ne trükkös! • Mellékhatásoktól tartózkodni! • Nem triviális szintaxist kerülni, akkor is, ha a C nyelv szerint az egyértelmű (a+++b) • Nem feltétlenül kell haragudni a break-re és a continue-re! Óra végén látni fogjuk, hogy C++-ban még a „goto”-t is gyakran használjuk (bár nem így hívjuk).
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
-7-
Mi történik, ha x > 2.3 ? while (i < 12 && q != 1 && k > 87 && u < 3) { ................................... ................................... if (x > 2.3) { q = 0; } else { .................................. .................................. .................................. .................................. .................................. C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
-8-
2011.02.15.
-9-
és itt ? while (i < 12 && k > 87 && u < 3) { ................................... ................................... if (x > 2.3) { break; } .................................. .................................. .................................. .................................. .................................. C++ programozási nyelv © BME-IIT Sz.I.
Általános kódolási tanácsok/2 • Makrókat kerüljük, ha lehet #define max(a,b) a > b ? a : b int a1 = 1; int x = max(a1&7, 3); // x = ??? #define max(a,b) (a) > (b) ? a : b
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 10 -
Általános kódolási tanácsok/2 • Memória foglalás: ki foglal és ki szabadít? char *valami(char *); // lefoglal? Mit csinál? • Ha foglal, kinek kell felszabadítani ? • Oda kell írni kommentbe! • Összetartozó adatok struktúrába • Konstansok, enum • Style guide (pl. google-styleguide) – elnevezéstől a formázásig minden le van írva
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 11 -
C++ újdonságok, bővítések • Struktúranév típussá válik • Csak preprocesszorral megoldható dolgok nyelvi szintre emelése (const, enum, inline) • Kötelező prototípus, névterek • Referencia, cím szerinti paraméterátadás • Többarcú függvények (overload) • Alapértelmezésű (default) argumentumok • Dinamikus memória nyelvi szint. (new, delete) • Változó definíció bárhol C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 12 -
Típusok • • • • • • • •
logikai char egész felsorolás valós mutató referencia void
integrális aritmetikai
• összetett adatszerkezetek (tömb struktúra) és osztályok
skalár
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 13 -
Változók mérete (ism.) sizeof kifejezés, vagy sizeof(típus) sizeof(char) --> sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(float) <= sizeof(short) >= sizeof(long) >=
1 byte (>= 8 bit) sizeof(short) sizeof(int) sizeof(long) sizeof(double) 16 bit 32 bit
Az int mindig az adott architektúra legoptimálisabb egésze. C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 14 -
sizeof operátor (ism.) int a[100]; int s = sizeof a; // s = ??? ................. void f(int a[], int b) { int s = sizeof a; // s = ??? int c[b]; // változó méretű tömb (C99 !) a = sizeof c ; // futási időben értékelődik ki } // sizeof: leginkább a malloc-hoz ! C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 15 -
Logikai típus bool false true aritmetikai bool automatikus típuskonverzió, ahogyan a C-ben megszoktuk.
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 16 -
Aritmetikai és logikai konverzió Aritmetikai típus értékkészlete
bool
0 = hamis, a többi = igaz
0 vagy 1
bool b1, b2, b3; int i; b1 = true; b2 = 3; i = b2; b3 = false; (b2 == true, i == 1) C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 17 -
struct és rokonai struct komplex { float re; float im; }; srtruct lista_elem { int i; lista_elem *kov; }; C++ programozási nyelv © BME-IIT Sz.I.
c++-ban a név típus értékű
önhivatkozó struktúránál kényelmes
2011.02.15.
- 18 -
Konstans #define PI 3.14 helyett const float PI = 3.14; const: Típusmódosító amely megtiltja az objektum átírását (fordító nem engedi, hogy balértékként szerepeljen) Mutatók esetén: const char * p; //p által címzett terület nem módosítható char * const q; //q-t nem lehet megváltoztatni C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 19 -
Két trükkös próbálkozás const int x = 3; int *px = &x; *px = 4; void f(int *i) { *i = 4; } const int x = 3; f(&x);
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 20 -
Felsorolás típus enum szinek { típus piros, sarga, zold = 4 }; Szigorúbb ellenőrzés, mint az ANSI C-ben. Pl: fordítási hiba
szinek jelzo; jelzo = 4; jelzo = szinek(8); C++ programozási nyelv © BME-IIT Sz.I.
nincs hiba, de meghatározatlan érték létrehozása 2011.02.15.
- 21 -
Prototípus Előrehivatkozáskor kötelező Tipikus C hiba: double z = sqrt(2);
C feltételezi, hogy int
(double) kellene
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 22 -
Miért okoz problémát ? a függvényt hívó rész double z=sqrt(2);
a hívott függvény double sqrt(double x) { verem
int
double
regiszter
int
double
C++ programozási nyelv © BME-IIT Sz.I.
x . . return res; ...}
2011.02.15.
- 23 -
Mutatók és címek (ism.) • Minden változó és függvény memóriában levő helye (címe) képezhető. (pl: &valtozo) • Ez a cím ún. pointerben vagy mutatóban tárolható. • A pointer egy olyan típus, amelynek az értékkészlete cím, és mindig egy meghatározott típusú objektumra mutat. int i, *ip; float f, *fp;
int-re mutató pointer float-ra mutató pointer
C++ programozási nyelv © BME-IIT Sz.I.
ip = &i; fp = &f; 2011.02.15.
- 24 -
Indirekció (ism.) *ip = 13;
int i;
float f;
13 i cime int *ip;
float *fp; ip = &i
Memória
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 25 -
Értékparaméter (ism.) • A paraméterek nem változhatnak meg, mivel azok értéke adódik át. • Azok eredeti tartalma az eredeti helyen megmarad. • A függvény csak a függvényértéken keresztül tud a külvilágnak eredményt szolgáltatni. (Ez sokszor kevés.)
érték
változó v. konstans
fv.érték
függvény
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 26 -
Változóparaméter (ism.)
cím
változó
fv.érték
függvény
• A paraméter címe adódik át, így annak tartalma felhasználható, de • meg is változtatható. • A magas szintű nyelvek elfedik ezt a trükköt. Sem az aktuális paraméterek átadásakor, sem a formális paraméterekre való hivatkozáskor nem kell jelölni. • Csupán a paraméter jellegét (változó) kell megadni.
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 27 -
Referencia Referencia: alternatív név tipus& int i = 1; int& r = i; // kötelező inicializálni, mert // valójában egy cím int x = r; // x = 1; r = 2; // i = 2; C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 28 -
Változó paraméter referenciával C: void inc(int *a) { (*a)++; } könnyen int x = 2; lemarad inc( &x);
C++: void inc(int &a) { a++; nem kell } jelölni a int x = 2; címképzést híváskor inc(x);
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 29 -
Paraméterátadás • érték szerint – skalár – struct
• cím szerint (tömb, változtatni kell, hatékonyság) – típus& – típus*
• Pointer paraméter és a változtatandó paraméter szétválik. C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 30 -
Paraméterátadás /2 • Pointer, referencia + const használatával a hozzáférés jól szabályozható: struct Data { double dx[1000]; int px[2000]; } void f1(Data);
// értékparaméter!
void f1(const Data* ); void f2(const Data&); void f3(Data*); void f4(Data&);
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 31 -
Függvényhívás mint balérték int x; … int& f( ) { return x; } … main( ) { f( ) = 5; f( )++; f( ) = f( ) + 2; } C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 32 -
Inline #define max(a,b) (a) > (b) ? a : b
x = 8, y = 1; x = max(x++, y++); x,y = ? inline int max(int a, int b) { return(a > b ? a: b); } Nincs trükk. Pontosan úgy viselkedik, mint a függvény, de a hívás helyére kell beilleszteni a kódot (lehetőleg). C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 33 -
Függvény overload int max(int a, int b) { return(a > b ? a: b); } double max(double a, double b) { return(a > b ? a: b); }
int x = max(1, 2);
double f = max(1.2, 0.2);
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 34 -
Függvény argumentumok • Konvertert írunk, ami tetszőleges számrendszerbe tud konvertálni. A számrendszer alapját paraméterként kapja. char *int2Ascii(int i, int base = 10); Csak az argumentumlista végén lehetnek default argumentumok, akár több is. • f(), f(void) - nincs paraméter • f(...) - nem kell ellenőrizni • f(int a, int) - nem fogjuk használni C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 35 -
Deklaráció és definíció • A deklarációs pont továbbra is legtöbbször definició is: – int a; float alma; – de: int fv(int x); - nem definició
• A típus nem hagyható el ! • Több deklaráció is lehet, – extern int error; – extern int error;
• Definició csak egy! C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 36 -
Ott deklaráljunk, ahol használjuk y = 12; int z = 3; for (int i = 0; i < 10; i++) { élettartam, hatókör z += i; u.a, mint a C-ben int k = i – 1; y *= k; i, és k itt már nem létezik ! (sajnos vannak eltérések) }
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 37 -
Deklarációk feltételben és ciklusban if (double d = fx(y)) { cout << d; } else { d = 21.2; cout << d; }
C++ programozási nyelv © BME-IIT Sz.I.
for (int i = 10; i--;) cout << i; while (char ch = get()) { cout << ch; }
2011.02.15.
- 38 -
Névterek, scope operátor • A moduláris programozás támogatására külön névterületeket definiálhatunk. • Ezek neveire (azonosítóira) a hatókör (scope) operátorral (::), vagy a using namespace direktívával hivatkozhatunk. namespace Proba { int alma; float fv(int i); char *nev; } C++ programozási nyelv © BME-IIT Sz.I.
Proba::alma = 12; float f = Proba::fv(3); using namespace Proba; alma = 8; float f = fv(3); 2011.02.15.
- 39 -
using direktíva • A using namespace direktívával a teljes névteret, vagy annak egy részét láthatóvá tehetjük: using namespace Proba; alma = 8; float f = fv(3); using Proba::alma; using Proba::fv; alma = 8; float f = fv(3); Proba::nev = "Dr. Bubo"; C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 40 -
standard I/O • cin • cout • cerr
iostream, iostream.h
Az "új" változatot illik használni! (névtér, wchar_t,...)
cout << "i = " << i << '\n'; cin >> i;
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 41 -
Miért iostream ? C-ben ezt írtuk: printf("i=%d j=%d\n", i, j); C++-ban ezt kell: cout << "i = " << i << " j=" << j << endl; Kinek jó ez ? • A printf, scanf nem biztonságos! Nem lehet ellenőrizni a paraméterek típusát. • A printf, scanf nem bővíthető új típussal. • Lehet vegyesen ? (sync_with_stdio()) C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 42 -
Dinamikus memória #include <malloc.h> .... struct Lanc *p; p = malloc(sizeof(Lanc)); if (p == NULL) .... free( p );
Lanc *p; p = new Lanc; .... delete p; Tömb: int *p; p = new int[10]; delete[] p;
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 43 -
Dinamikus memória /2 C: malloc(), free(), realloc() • C++-ban is használható de csak nagyon körültekintően, ugyanis nem hívódik meg a megfelelő konstruktor ill. destruktor. Ezért inkább ne is használjuk. C++ (operátor): new, delete, new[], delete[] • Figyeljünk oda, hogy a tömböket mindig a delete[] operátorral szabadítsuk fel. C++: nincs realloc()-nak megfelelő. C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 44 -
Mi van, ha elfogy a memória ? void OutOfMem() { cerr << "Gáz van\n"; exit(1); } int main() { set_new_handler(OutOfMem); double p* = new double; .... C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 45 -
Kivételkezelés • Hibák kezelése gyakran nem a hiba keletkezésének helyén történik. (Legtöbbször nem tudjuk, hogy mit kell tenni. megállni, kiírni valami csúnyát, stb.) • C++ típusorientát kivételkezelése: – figyelendő kódrészlet kijelölése (try) – kivétel továbbítása (throw) – esemény lekezelése (catch)
C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 46 -
Kivételkezelés = globális goto
Kivétel2
Kritikus műveletek
Kivétel1
További műv.
C: setjmp( ) longjmp( ) C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 47 -
2011.02.15.
- 48 -
Kivételkezelés/2 try { ..... Kritikus művelet1 if (hiba) throw kifejezés_tip1; ..... Kritikus művelet2 if (hiba) throw kifejezés_tip2; } catch (típus1 param) { ..... Kivételkezelés1 } catch (típus2 param) { ..... Kivételkezelés2 } ... további utasítások C++ programozási nyelv © BME-IIT Sz.I.
Kivételkezelés példa Hiba észlelése
double osztas(int y) { if (y == 0) throw "Osztas nullaval"; return((5.0/y); }
A típus azonosít
int main() Kritikus szakasz { try { cout << "5/2 =" << osztas(2) << '\n'; cout << "5/0 =" << osztas(0) << '\n'; } catch (const char *p) { cout << p << '\n'; Kivétel kez. } } C++ programozási nyelv © BME-IIT Sz.I.
2011.02.15.
- 49 -
Kivételkezelés a memóriára #include
#include using namespace std; int main() { // set_new_handler(0); try { while(true) double *p = new double; } C++ programozási nyelv © BME-IIT Sz.I.
catch (bad_alloc) { cerr << "Gaz van\n"; } cerr << ”Vege\n”; return(0); }
2011.02.15.
- 50 -