Programozás s 2 Objektum Orientált Programozás C++ nyelven utolsó változtatás s 2008.04.12.
C++ Történetileg a C nyelv továbbfejleszt bbfejlesztésese Ennek előnyei: C programozó azonnal programozhat C-ként C C++-ban használva a plusz kényelmi k lehetőségeket Kulcsszavai azonosak/hasonlóak ak a C-velC Lehet vele hatékony OOP programokat készk szíteni Hátránya: nincs késztetk sztetés s az OOP gondolkodásm smódjának elsajátítására
C++ A C++ mintaprogramok letölthet lthetőek ek a tanszéki web oldalról: l: www.fat.bme.hu/student/ Amit itt esetleg nem találnak lnak meg, az pedig a www.fat.bme.hu/pub/programozas2/ /Programozas2/ címen biztos megtalálhat lható.
Az első C++ program // A világ keletkezése és s pusztulása. sa. A // -lal kezdődő szöveg megjegyzés. #include <iostream> // innen jön j n az std::cout (nincs benne '.h'!) class Univerzum // a világnak mint objektumnak a deklaráci ciója // leírja az objektumot, de nem hoz létre l egyet sem. public: // enélk lkül l kívülrk lről l nem látnl tnánk nk az ezután n felsorolt függvf ggvényeket Univerzum() // 'constructor' ez hozza majd létre az objektumot std::cout << "Big bang\n"; // szöveg kiiratás s a képernyk pernyőre re (console output), végén v n soremelés ~Univerzum() // 'destructor' megsemmisíti az objektumot std::cout << "Viszl" Viszlát\n"; // szöveg kiiratás s a képernyk pernyőre re (console output) ; // Globális lis terület (minden a -eken kívül k l ) Itt jön j n létre l a világ. // Lefut a constructora és s kiírja a szöveget // ez kell, ez az első függvény ami meghívódik a globális lis változv ltozók // létrejl trejötte tte után. Most nem csinál l semmit n a "main()' lefutott a globális lis változv ltozók k megsemmisülnek. Lefut az "azuniverzum" destructora Univerzum azuniverzum; int main() // miután a "main()' lefutott a glob
C++ programok futása Általánosságban a programok futása során 1. Elősz ször r a globális lis objektumok jönnek j létre. l Elősz ször lefoglalódik a memória az objektumoknak, utána lefut a constructoruk. Alaptípusoknak pusoknak nincs constructoruk. Jelen esetben a constructor-t t mi definiáltuk, és s lefutásakor szöveget ír r ki. 2. A main() fut le. Jelen esetben nem csinál l semmit (csak( boldoggá teszi a C programozókat ). ). Minden globális lis függvf ggvényt (most nem volt egy sem) vagy a main, az általa hívott h függvényláncolat, ncolat, vagy az objektumok hívnak. h 3. A main befejezése után n a globális lis objektumok eltünnek. Eközben zben lefutnak a destructor-jaik. Jelen esetben a destructor-t t mi definiáltuk, és s lefutásakor szöveget ír r ki.
Megjegyzések A Microsoft Visual Studio (2005) beli C++ fordítónak meg kell adni egy stdafx.h nevű (akár üres) header fájl is az <iostream> előtt! Tovább bbá minden új j projekt (solution) eseten az alábbi részt r magától l beírja:. #include "stdafx.h" stdafx.h". int t_main(int argc, _TCHAR* argv[]) return 0; A _tmain() valójában egy MAKRÓ,, ami a mi esetünkben main()-nel nel ekvivalens. Így definiált lták: #define _tmain main A _TCHAR pedig egy típus, t ami most char -ral ekvivalens. Így definiálj lják: typedef char _TCHAR; A main() függvf ggvénynek vagy nincs argumentuma, vagy 2 vagy 3 van neki: int main(int argc, char *argv[], [char char *env* env[] []] ) Az argc az argv karakter mutatókat tartalmazó tömb elemeinek száma ma,, amely mutatói i a paranzssorbeli paraméterekre mutatnak. a 0. elem a végrahajtott v program neve. Ha az env tömb is jelen van a futtatási környezet (SET) elemeire mutató mutatókat tartalmazza. Pl.. ha a programot így indítottuk C:\sajat könyvtk nyvtárból l parancssorból l : program d d valami akkor argc == 3 és s az argv értékei: argv[0]= [0]="C:\sajat\program", argv[1]= "-d", argv[2]= "valami" Nem minden rendszeren kerül l be a 0. paraméterbe a teljes elérési út
Feladat Módosítsuk a programot úgy, hogy több t univerzumot hozzon létre. l Vajon milyen sorrendben törtt rténik ez? És s a megsemmisülésük? Adjunk minden világnak egy egyedi azonosítót, t, akkor megtudhatjuk:
A módosm dosított Univerzum // egy univerzum, amelyik tudja magáról l melyik class Univerzum // a világnak mint objektumnak a deklaráci ciója Az // leírja az objektumot, de nem hoz létre l egyet sem. public: // enélk lkül l kívülrk lről l nem látnl tnánk nk az ezután n felsorolt függvf ggvényeket Univerzum(int int melyik) : _azon(melyik) // : utáni rész r a 'preambulum' ld. alább std::cout << "A" A " << "_azon" << ". Big Bang \n"; ~Univerzum() std::cout << "Viszl" Viszlát\n"; private: // ezt csak k az objetum maga látja l (adatrejtés) // Jelölj ljük k a privát t változv ltozókat egy aláhúzás s karakterrel! const int _azon; // const ha egyszer létrejl trejött tt nem változv ltozhat meg az értéke // ezért nem lehet értéket adni neki a belül l csak a // 'preambulum'-ban. ban. A preambulum előbb hajtódik végre, v mint // az objektum létrehozl trehozása ;
Több Univerzum létrehozl trehozása Ennek használata:. Univerzum univ1(1), univ2(2); main() Univerzum univ(3);
Objektumokbeli függvények/módszerek Hogy lehetne megkérdezni a világt gtól, hogyh ő melyik? class Univerzum public:... int Azon() const // a const itt azt jelenti, hogy ez a függvf ggvény // nem változtat v meg egy változv ltozót t sem return _azon_ azon; // csak const függvf ggvények férhetnek f hozzá a // const objektumokhoz,, ill const objektumnak //csak const függvf ggvényeit hívhatjukvhatjuk meg // ez látszl tszólag egy költsk ltséges függvf ggvényhívás, de itt ingyen van... ;
Háttér r informáci ció Egy adott osztálynak megfelelő objektumok mérete m az objektumban tárolt adatok (konstansok és s változv ltozók) számára lefoglalt memória méretek összege. A függvf ggvények minden objektumra ugyanazok és s a méret számításban sban nem jelennek meg. Figyelem: az adatok mérete m lehet nagyobb, mint amit megadtunk! Ugyanis a korszerű processzorok valamivel gyorsabban érik el az adatot, ha az 'dupla szó' ' határra van illesztve. Ekkor pl. egy char típust pusú adat 4 bájt b helyet foglal el, amiből l csak 1-et 1 használ, a többi t csak helykitölt ltés. Honnan "tudja" egy osztály egy függvf ggvénye mely objektum adatait használja? Minden függvf ggvény kap egy adott objektumra mutató pointert is. Ezt a fordító program rakja bele első paraméterk terként, nekünk nk sosem kell megadni. Ennek neve: this pointer. A this pointert mi is használhatjuk (néha kell is).
Beágyaz gyazás Minden univerzumban van anyag: class Anyag public: Anyag(int mi):_azon(mi) cout << _azon << ". anyag létrejött\n"; ~Anyag() cout << _azon << ". anyag megsemmisült lt\n"; private: const int _azon; ;
Beágyaz gyazás s II. class Univerzum // az _anyag létrehozása a preambulumban azelőtt törtt rténik, hogy az public: // objektum létrejl trejönne // ezért amikor deklaráljuk ljuk alább nem kell argumentumot adni neki (nem ott hozzuk létre) l // A preambulumbeli sorrend lényegtelen. l Az értékadás s a deklarálási sorrend szerint törtt rténik Univerzum(int melyik, int anyag) : azon(melyik), anyag(_anyag) anyag) cout << _azon << ". Big Bang\n"; n"; ~Univerzum() cout << _azon << ". elpusztult\n"; private: const int azon;_ const Anyag anyag;_ ; Univerzum univ1(1,100), univ(2,200);
Beágyaz gyazás s III. A beágyaz gyazás s egy "van" neki" " kapcsolat. A létrehozl trehozás s sorrendje: elősz ször r az Univerzum _azon konstansa jön j n létre l és s kap értéket, majd a beágyazott _anyag objektum jön n létre l benne a saját _azon konstansával, aminek semmi köze k az őt t tartalmazó Univerzum objektum azonos nevű konstansához. ez a beágyazott objektum azért lehet konstans, mert értéke nem változik v amíg g a beágyaz gyazó osztály él.
Beágyaz gyazás s IV. A megsemmisülés s sorrendje elősz ször r a beágyaz gyazó objektum, az Univerzum pusztul el utána a beágyazott objektum, az Anyag
Objektum élettartama Legyen T egy típus t (pl. char, int, Univerzum) Globálisan, lisan, vagy blokkon belül l hozzunk létre l egy T típust pusú változót: t: T t; t A fordító lefoglal a t-nek t megfelelő nagyságú memóri riát (és s lefuttatja T constructor-át, t, ha van neki). Valahányszor t-t t használjuk erre a memóri riára ra hivatkozik a gépi g kódban. k A program (blokk) végén v t automatikusan megsemmisül (destructor-a a lefut).
Referenciák T & rt = t; rt egy e referencia t re. Referenciát t csak a definiálása során n végzett v értékadással hozhatunk létre. l Nem változtathatv ltoztatható. A referencia a változv ltozó egy másik m neve (alias). Hasznos függvf ggvényhívásban, ha több t értéket akarunk visszaadni (C-ben erre mutatókat kellene használni): int fuggveny(int i, int &j, int &k); Ez a függvf ggvény 3 értéket ad vissza. A szokásoson soson kívül k l j-t j és k-t t is. Ezek használata függvf ggvényen belül l olyan, mint az ott definiált változv ltozóké lenne.
Mutatók T *pt; ez a deklaráci ció egy T típust pusú változóra mutató mutatót (pointert) hoz létre. l A fordító csak egy mutatónyi memóri riát foglal le, ami nem mutat érvényes memória címre! c Használata: Pl. a T t,*ptt *pt; deklaráci ció és pt = & t; értékadás s után t és *pt ugyanaz a változv ltozó A pt = new T; dinamikus memória foglalással (ekkor T construc- tora a is lefut).. A pt t t a program vége v előtt fel kell szabadítani: delete pt; -vel.. (ekkor( a pt által mutatott T objektum destructora is lefut). A pt = new T[sizeT size]; ; dinamikus memória foglalással (T constructora minden elemre lefut).. A pt t t a program vége v előtt fel kell szabadítani: delete [] pt; -vel.. (ekkor( minden elem destructora lefut) Tömböt t csak akkor lehet ily módon m létrehozni, l ha a T osztálynak van argumrntum nélkn lküli li T() constructora.
Mutatók k II. Mutatókat csak akkor használjunk, ha nincs más s mód! m Mutatók k használat latának veszélyei: 1. Nem inicializált lt mutatók 2. Felszabadított memóri riára ra mutató mutatók 3. Egy tömb t vége v utánra mutató mutatók 4. Mutatók, amik másra m mutatnak, mint gondolnánk nk 5. Mutatók, amikről l fogalmunk sincs hova mutatnak
Mutatók k III. Mutató aritmetika (a C és s C++ előnye): const int size=100; T t, *pt, *p; pt = new T[size]; // pt a size elemű tömb első (0 indexű) ) elemére mutat p = pt; ++p; // p most a pt által mutatott tömb t 2. (1 indexű) ) elemére mutat p = pt + 2; // p a pt által mutatott tömb t 3. (2 indexű) ) elemére mutat Ezek ekvivalensek: *(pt+2) pt[2] Növelő operátor: ++, ill. csökkent kkentő operátor: -- Van előzetes zetes- és s utólagos lagos- verziójuk, ++p és p++,, ill. ++p és p Pl. legyen int a[2] a = 3, 4; és int *pi = &a; ekkor *++pi = 5; 5 után n a = 3, 5 lesz, míg g ehelyett *pi++ = 5 után a = 5,4 lesz.. pip mindkét t esetben a[1]-re fog mutatni.
Kitérő: : Mutatók k IV. T const *p; vagy const T *p; p egy mutató ami konstans T objektum(sorozat)ra mutat. T * const p = & t; t p egy konstans mutató,, ami egy T objektumra mutat. Nem lehet megváltoztatni (mintha hivatkozás s lenne). A deklaráci ciójával egyidejűleg kell definiálni is. A p által mutatott értékek megváltoztathat ltoztathatóak. ak. T const * const p = & t; t p is és s az általa mutatott változv ltozó is konstans
Leszármaztat rmaztatás Írjuk le az embereket, azaz a férfiakat f és s a nőket. n Minden Ember-nek vannak közös k s tulajdonságai: feje, szeme, szája, stb. Ezért célszerc lszerű az összes Embert egy EMBER osztállyal definiálni. Tudjuk, hogy minden Nő és s Férfi F egyúttal Ember is. Ugyanakkor a férfiaknak f és s nőknek n vannak csak rájuk jellemző tulajdonságaik. Ezért írjuk le a nőket n a NO a Férfiakat F a FÉRFI F osztallyal. Beágyazhatn gyazhatnánk nk minden NO-be és s FERFI-be egy EMBER-t, de ez nem a keresett kapcsolat!! Nem azt akarjuk pl. leírni, hogy "Minden" nőben n van valami" ember,, hanem azt, hogy "Minden" nőn ember".
Leszármaztat rmaztatás s II. Próbáljuk meg a definíci ciókat (az ún. interface-t) t) és a megvalósítást/haszn st/használatot különvk nválasztani! Rakjuk az osztálydefin lydefiníciókat külön k n fájlba. f Ennek kiterjesztése se rendszerint.h. ('header' fájl) f Tehát t az alábbi forrás s fájljaink f lesznek: nemek.h az osztálydeklar lydeklarációkkal nemek.cpp a definíci ciók main.cpp ebben van a main() a futtatáshoz Egy bonyolultabb programban több t.h és s.cpp fájl f van. A main() függvf ggvény csak egyben lehet.
Leszármaztat rmaztatás s III. A teljes Visual C++ os projekt a Tanszéki honlapról l letölthet lthető és (bővebb) magyarázatokat is tartalmaz A nemek.h fájl f tartalma (ahhoz, hogy ezt a fájlt a fordító értelmezni tudja azután n lehet csak használni, miután n az iostream-et et már m r include-oltuk)
nemek.h I. #if!defined(_nemekh) #define _nemekh // feltételes teles fordítási blokk eleje. A blokk vége v (#endif) a nemek.h IV oldalon namespace nemek class SZOVEG // segs egéd d osztály a nevek tárolt rolásához. public: SZOVEG(char txt[] ) _pszoveg = new char[ strlen(txt)+1]; // dinamikus memória a szövegnek és s az azt lezáró \0-nak strcpy(_pszoveg, txt); // szöveg átmásolása a pszoveg-be a záróz 0 karakterrel együtt ~SZOVEG() delete [] _pszoveg; // a lefoglalt t memória felszabadítása sa char const *Szoveg() const return _pszoveg; private: char *_pszoveg; // ez nem lehet konstans ;
nemek.h II. class EMBER public: EMBER(char nev[]); ; // a függvf ggvény törzse t máshol m van ~EMBER(); const char *Neve() const return _nev.szoveg(); virtual char *Megszolitasa()=0; // "tisztán n virtuális függvf ggvény" majd csak a leszármaztatott osztályban lesz definiálva. Emiatt EMBER objektumot nem lehet létrehozni minden leszármaztatott osztályban más m s lesz void Koszonti(EMBER &e) ; // Bármilyen B EMBER-t t elfogad protected: // Mintha private: lenne, de a leszámaztatott osztály is látjal const SZOVEG _nev; // az EMBER élete során n nem változikv ;
nemek.h III. class FERFI: public EMBER // azaz a FERFI az egy EMBER és s annak minden public és s protected változóját és s módszerm dszerét t eléri public: FERFI(char nev[]): EMBER(nev); ~FERFI() char *Megszolitasa() return "Uram"; ;
nemek.h IV. class NO: public EMBER public: NO(char nev[]): EMBER(nev); ~NO() char *Megszolitasa() return "Hölgyem"; ; // A nemek namespace vége // a nemek.h I. oldalon kezdett feltételesen telesen lefordítand tandó blokk végev #endif
nemek.cpp #include "stdafx.h" // ez az előre fordított header-ek ek miatt kell. Microsoft specialitás #include <iostream> // ebben van a << definíá íálása using std::cout; using std::endl; // ezután n nem kell pl std::cout -ot írni. Elég g a cout. #include "nemek.h" using namespace nemek; // hogy ne kelljen alább nemek::ferfi-t t használnunk EMBER::EMBER(char nev[]):_nev(nev) cout << _nev.szoveg() << " vagyok "; EMBER::~EMBER() cout << "Viszlát! mondja " << _nev.szoveg() << endl;
nemek.cpp II. void EMBER::Koszonti(EMBER &e) cout << "Jó napot " << e.megszolitasa() << "!" << endl; Miután n a Megszólítás() s() virtuális mindíg g a leszármaztatott objektumnak megfelelő hívódik meg. Ha nem az lenne, akkor az EMBER osztály lyé hívódna meg.
nemek.cpp III. FERFI::FERFI(char nev[]): EMBER(nev) cout << "és" s férfi." f << endl; NO::NO(char nev[]): EMBER(nev) cout << "és" s nő." n << endl;
main.cpp #include "stdafx.h" // ez az előre fordított header-ek ek miatt kell. Microsoft specialitás #include <iostream> // ebben van a << definíá íálása using namespace std; // ezután n nem kell pl std::cout -ot írni. Elég g a cout. #include "nemek.h" // itt definiáltuk az osztályokat egy saját t namespace- en beül using namespace nemek; // hogy ne kelljen alább nemek::ferfi-t használnunk FERFI adam("ádám"); m"); // adam nem csak FÉRFI, F de EMBER is NO eva("éva"); va"); // eva nem csak NO, de EMBER is
main.cpp II. // a Koszonti() függvf ggvény EMBER-t t vár, v mégis m 'tudja', hogy FERFI-t t vagy NO-t t köszk szönt int main() cout << "--------------" --------------\n"; adam.koszonti(eva); eva.koszonti(adam); cout << "--------------" --------------\n"; return 0;
Leszármaztat rmaztatás IV. A leszármaztat rmaztatás s egy "az" egy" " kapcsolat: a leszármaztatott objektum az egy szülő objektum plusz tulajdonságokkal A leszármaztatott objektum örökli a szülő adat tagjait és s módszereit, m kivéve ve a következk vetkezőket: ket: Constructor és s destructor értékadás s operátora: operator=() friend függvények és s osztályok A leszármaztatott objektum átdefiniálhatja az anyaobjektum módszereitm A leszármaztat rmaztatás s lehet: public, protected, vagy private:
Leszármaztat rmaztatás V. Hozzáférés s szabályoz lyozása a leszármaztat rmaztatás s módja m szerint Leszármaztat rmaztatás s módjam class B : public A class B : private A class B:protected A ami A számára public protected private public protected private public protected private az B számára public protected nem hozzáférhet rhető private private nem hozzáférhet rhető protected protected nem hozzáférhet rhető
Megjegyzés class A public: void f(); void g(); class B : private A // ez minden A beli public vagy protetced adatból l private-t t csinál // B-ben B [ B nem fér f r hozzá A private tagjaihoz] public: using A::f; // DE az A beli public f() függvf ggvény public lesz B-ben B is // [f után n nincs ()!], miközben g() private függvf ggvénye B-nekB
Leszármaztat rmaztatás V. A létrehozl trehozások sorrendje: elősz ször r a szülő objektum jön j n létre l a szokásos sos módon. Ha vannak benne beágyaz gyazások, akkor elősz ször r azok, utána az őket tartalmazó objektum ezután n jön j n létre l a leszármaztatott objektum ugyanilyen módon. m A megsemmisülés s sorrendje a létrehozl trehozás sorrendjének nek a fordítottja.
Hibakezelés s I. Programhibák k lekezelésének helyes módszere m a kivétel (exception)) kezelés. A problémás s részeket r egy try blokkba rakjuk Hiba esetén n a try blokkban végrehajtott v függvf ggvény egy kivételt ún. exception-t t dob. Pl. int HibatAdoFuggveny(char szname[]) throw( ) // a throw(...) a függvf ggvény név n v után n azt jelzi, hogy vmilyen // egyelőre határozatlan exception-t t dobhat f = fopen(szname,, "wb" wb"); if(!f (!f) throw FileIOException eio("fájl megnyitási hiba");... return 0; A throw(...) a függvf ggvénynév v után n opcionális. Ha azt akarjuk kifejezni, hogy egy függvény nem dobbhat exception-t t akkor a függvf ggvény neve után n a "..."" argumentum nálkn lküli li throw() t írjunk.
Hibakezelés s II. A try blokk után n egy vagy többt catch blokkban kapjuk el a dobott exception-t Pl. try... esetleg hibát okozó függvényhívások... catch (OutOfMemoryException &e) hibakezelés I. // csak OutOfMemoryException típust pusú exception re jön j n ide throw; // ugyanezt az exception-t t továbbk bbküldi catch (...) // minden eddig nem kezelt Exceptionra ide jönj hibakezelés II. // innen nem küldjk ldjük k tovább
Operátor túlterhelt lterhelés s (overloading) A C++ ban szinte minden operátor túlterhelhető.. Pl: = + - * / += -= = *= /= ++ -- == () [] ^ ~ new -> & Nem túlterhelhetőek: ek:.? sizeof Csak olyan túlterhelt lterhelések lehetségesek, amelyekben legalább az egyik paraméter nem beépített típus. t
Operátor túlterhelt lterhelés Szintaxis (példa) 1. osztály deklaráci ción n belül: class COMPLEX public: COMPLEX(double r,double i) : real(r), im(i) double real,im; COMPLEX operator+(const COMPLEX &c2) COMPLEX c(0,0); // ez egy lokális lis változv ltozó c.real = real + c2.real; // mert nem akarjuk megváltoztatni c.im =im + c2.im; // az objektumot, amihez hozzáadunk return c; // érték k alapján n adja vissza, ezért nem baj // hogy a lokális lis változv ltozó megsemmisül ;
Operátor túlterhelt lterhelés Szintaxis (példa) 1. osztály deklaráci ción kívül class COMPLEX public: COMPLEX(double r,double i) : real(r), im(i) double real,im; ; COMPLEX operator+(complex &c1, const COMPLEX &c2) COMPLEX c(0,0); c.real = c1.real + c2.real; c.im = c1.im + c2.im; return c;
Operátor túlterhelt lterhelés Bármelyik használata lata: using namespace std; int main() COMPLEX a(1,-1), 1), b(3,-3); 3); cout << "a: " << a.real << " + " << a.im << "i\n"; cout << "b: " << b.real << " + " << b.im << "i\n"; cout << "a + b= " << (a+b).real << " + " << (a+b).im << "i\n"; cout << "a + b + b= " << (a+b+b).real << " + " << (a+b+b).im << "i\n"; // próbáljuk ki nem lokális lis változv ltozóval az operator+()-ban...
Teljesebb példa class COMPLEX public: COMPLEX():_re(0),_im(0) COMPLEX(double re) : _re(re),_im(0) COMPLEX(double re, double im): _re(re), _im(im) COMPLEX &operator=(double i) _re = i; _im = 0; return *this; COMPLEX &operator=(const COMPLEX c) _re = c._re; _im = c._im; return *this; COMPLEX operator+(double i) COMPLEX c; c._re = _re + i; return n c; COMPLEX operator+(const COMPLEX c) COMPLEX t; t._re = _re + c._re; t._im = c._im; ; return t; COMPLEX operator*(const COMPLEX c) COMPLEX t; t._re = _re*c._re -_im*c._im; t._im= _re*c._im+_im*c._re; return t; double Re() return _re; double Im() return _im; private: double _re, _im; ;
Template-ek ek Sokszor találunk lunk általános összefüggéseket, illetve feladatokat. Pl. két k t változv ltozó felcserélése: se: void swap(int &i, int &j) int k = i; i = j; j = k; void swap(complex &c1, COMPLEX &c2) COMPLEX c = c1; c1 = c2; c2 = c1; Ez függvény túlterheléssel l is megoldható,, mint itt, de van jobb módszer m is: az általános (generic) osztályok, eljárások a template-ek ek. Ekkor a fordítóprogram generálja a kódot. k
Template-ek ek template <class A> swap(a &a, A &b) A c = a; a=b; b = c; Használata lata: int i=3,j=4; swap <int>(i,j); COMPLEX a(1,1),b(2,-3); swap <COMPLEX>(a,b a,b); Megjegyzés: a swap template az std namespace-ben már r definiálva van.
Class Template-ek ek Nem csak függvf ggvénynek lehet template-je je, hanem osztályoknak is. Pl: template <class T> class GVECTOR // tetszőlege objektumok tárolására ra alkalmas vektor public: GVECTOR(int mini, int maxi) : _min(mini), _max(maxi), _dim(_max - _min + 1) _v = new T[_dim]; ~GVECTOR() delete [] _v; T &operator[](& operator[](int i) if(i < _min i > _max) throw "index hiba"; return _v[ i - _min];... // további operátorok, private tagok, stb ; A teljes példa p letölthet lthető a tanszéki honlapról. l.