c++ programavimas

C++ programavimo kalba Visa pagrindine teorija, klausimai ir atsakymai su pavyzdziais.

Įvadas į OOP, I/O bibliotekaProgramavimo kalbosn Procedūrinės (ankstyvos Fortran versijos)n Pagrindą sudaro funkcijos. Programos kodo ilgis iki kelių tūkstančių eilučių.n Struktūrinės (Pascal, C, Fortran, Basic, COBOL)n Pagrindą sudaro blokai (procedūros) ir duomenys, priskirti tiems blokams. Programos kodo ilgis iki 50 tūkstančių eilučių.n OOP (C++, Java, Visual Basic)Struktūrinis programavimasn Struktūrinio programavimo požymiai:n Programos lengvai suprantamos, testuojamos, modifikuojamas.n Struktūrinio programavimo taisyklėsn Naudojamos single-entry/single-exit valdymo struktūros;n Taisyklės1) Pradedama nuo “paprasčiausios” struktūrinės schemos;2) Bet kuris veiksmas, gali būti pakeistas dviejų veiksmų seka;3) Bet kuris veiksmas gali būti pakeistas valdymo struktūra ( if, if/else, switch, while, do/while, for)4) 2 ir 3 punktas gali kartotis

OOPn Išradėjai Ole-Johan Dhal ir Kristen Nygaard iš Oslo Universiteto ir Norvegijos Skaičiavimo centro (Norsk Regnesentral). OOP konsepcija buvo pristatyta 1966.

n OOP esmė – sudaryti realaus pasaulio atspindį programinio kodo struktūroje.importantStuff = new Object( ); importantStuff.money = 500; importantStuff.papers = 96; importantStuff.annPassport = “er246vjl”;importantStuff.bobPassport = “kl554mkt”;

importantStuff.jewelryBox = new Object( );importantStuff.jewelryBox.necklace1 = “Pearl”;importantStuff.jewelryBox.necklace2 = “Diamond”; C++ n C++ – tai C kalbos pratęsimas, priskiriant ją OOP kalbų grupei, todėl išlieka C ir C++ suderinamumas.n C++ geriau nei C, nes:n Išsamesnis klaidų tikrinamas, lengvesnė klaidų paieška;n Nuorodų (reference) panaudojimas funkcijų argumentuose ir grąžinamose reikšmėse yra patogesnis nei žymių (pointer).n Funkcijų perkrovimas (overloading) leidžia naudoti tuos pačius f-jų pavadinimus skirtingoms funkcijoms.n Vardų erdvės (namespace) leidžia geriau kontroliuoti vardų naudojimąC++ privalumai prieš Cn ~10 % didesnis programų našumas nei C;n Programos (didelės) lengviau taisomos bei modifikuojamos; n Dėl klasių pritaikymo lengviau naudojamos bibliotekosn Šablonai (template) automatiškai modifikuoja programinį kodą, taip palengvinami bibliotekų naudojimą;n Progaminis kodas gali viršyti 50.000 eilučių;

I/O bibliotekan I/O srautas – tai loginis įrenginys informacijos gavimui iš vartotojo ir informacijos perdavimui vartotojui.n I/O srautas siejamas su fiziniais įrenginais (ekranu, klaviatūra, pele, HDD) per C++ I/O sistemą t.y. I/O biblioteką, vadinamą iostream.n Tokia I/O sistema užtikrina vieningą trarką informacijos įvedimui/išvedimui.n I/O biblioteka suskirstyta į 4 failus:1. iostream.h 2. fstream.h 3. strstream.h 4. iomanip.h iostreamHeader File Descriptioniostream.h Defines a hierarchy of classes for low-level (untyped character-level) IO and high-level (typed) IO. This includes the definition of the ios, istream, ostream, and iostream classes.fstream.h Derives a set of classes from those defined in iostream.h for file IO. This includes the definition of the ifstream, ofstream, and fstream classes.strstream.h Derives a set of classes from those defined in iostream.h for IO with respect to character arrays. This includes the definition of the istrstream, ostrstream, and strstream classes.iomanip.h Defines a set of manipulator which operate on streams to produce useful effects.

Form of I/O Input Output Input and OutputStandard I/O istream ostream iostreamFile I/O ifstream ofstream fstreamArray of char I/O istrstream ostrstream strstreamApibrėžti standartiniai srautaiStream Type Buffered Descriptioncin istream Yes Connected to standard input (e.g., the keyboard)cout ostream Yes Connected to standard output (e.g., the monitor)clog ostream Yes Connected to standard error (e.g., the monitor)cerr ostream No Connected to standard error (e.g., the monitor)I/O operatoriain Įvedimo <<n Išvedimo >>

#include void main() {float A = 18.236;cout << “1. A=” << A << endl;cout << “2. A=” << A*2.0 << endl;}

I/On setw (n) n – lauko plotis simboliais,n setprecision (n) n – skaitmenų skaičius.

Jei setw nurodyto lauko dydžio skaičiui nepakanka, manipuliatorius ignoruojamas.Nuoroda setw galioja artimiausiai išvedamai reikšmei, o setprecission – iki naujonurodymo

#include #include main() {float A = 18.236;cout << “1. A=” << setw(9) << A << endl;cout << “2. A=” << setprecision(3) << A << endl;cout << “3. A=”<< setw(10) << setprecision(5) << A <main() {char sim;cout << “Ar dar dirbsite?( T/N ): “;do {sim = cin.get();sim = toupper(sim); }while((sim != ‘T’) && (sim != ‘N’));cout << “Jus pasirinkote : ” << sim << endl;}

Įvedimo klasėje metodas getline skirtas vienos eilutės įvedimui klaviatūra. Matome, kad paprastai įvedama eilutė iki pirmojo tarpo simbolio arba iki galo, jeigu tarpo simbolio nebuvo. Panaudoję getline metodą galima įvesti norimą simbolių skaičių: nurodomas skaičius. Jeigu tiek simbolių nebuvo, įvedami visi simboliai iki eilutės galo. Įvedama eilutė visuomet papildoma nuliniu simboliu.

main() {char A[30];int n;cout << “Iveskite eilute:n”;cin >> A; // Pirmasis eilutės žodiscout << “Eilute: *” << A << “*n”;cin.getline(A, 12); //Vienuolika simbolių ir ‘’cout << “Eilute: *” << A << “*n”;cin.getline(A, sizeof(A)); // Iki galo arba tiek, kiek telpacout << “Eilute: *” << A << “*n”;n = cin.gcount(); // Eilutės ilgis su nuliniu simboliucout << “n= ” << n << endl;}

I/O biblioteka (2 paskaita)

I/O operatoriain Išvedimo <<n Įvedimo >>

#include void main() {float A = 18.236;cout << “1. A=” << A << endl;cout << “2. A=” << A*2.0 << endl; }I/On setw (n) n – lauko plotis simboliais,n setprecision (n) n – skaitmenų skaičius.

Jei setw nurodyto lauko dydžio skaičiui nepakanka, manipuliatorius ignoruojamas.setw galioja artimiausiai išvedamai reikšmei, o setprecission – iki naujo nurodymo

#include #include void main() {float A = 18.236;cout << “1. A=” << setw(9) << A << endl;cout << “2. A=” << setprecision(3) << A << endl;cout << “3. A=“ << setw(10) << setprecision(5) << A <void main() {char sim;cout << “Ar dar dirbsite?( T/N ): “;do {sim = cin.get();sim = toupper(sim); }while((sim != ‘T’) && (sim != ‘N’));cout << “Jus pasirinkote : ” << sim << endl;}Įvedimo klasėje metodas getline() skirtas vienos eilutės įvedimui klaviatūra. getline( char* pch, int nCount, char delim = ‘n’ );

Matome, kad paprastai įvedama eilutė iki pirmojo tarpo simbolio arba iki galo, jeigu tarpo simbolio nebuvo.

Panaudoję getline metodą galima įvesti norimą simbolių skaičių (nurododant skaičių).

Jeigu tiek simbolių nebuvo, įvedami visi simboliai iki eilutės galo.

Įvedama eilutė visuomet papildoma nuliniu simboliu.

void main() {char A[30];int n;cout << “Iveskite eilute:n”;

cin >> A; // Pirmasis eilutės žodiscout << “Eilute: *” << A << “*n”;cin.getline(A, 12); //Vienuolika simbolių ir ‘’cout << “Eilute: *” << A << “*n”;cin.getline(A, sizeof(A)); // Iki galo arba tiek, kiek telpacout << “Eilute: *” << A << “*n”;n = cin.gcount(); // Eilutės ilgis su nuliniu simboliucout << “n= ” << n << endl;}

Įvedimo klasėje metodas getline() gali turėti trečią parametrą,nurodantį simbolį, kuriuo baigiamas įvedimas. Pavyzdyje parašytaraidė ‘Z’. Jeigu įvedamoje eilutėje jos nebus, tuomet bus įvedami visieilutės simboliai arba tik tiek, kiek nurodyta, jeigu eilutėje jų yra daugiau.

main() {char A[30];cout << “Iveskite eilute:n”;cin.getline(A, sizeof(A), ‘Z’);cout << “Eilute: *” << A << “*n”;}

ifstream, ofstreamĮvedimo srautu iš failo klasė ifstream ir išvedimo srautu į failą klasėofstream aprašytos faile fstream.h. Tai išvestinės klasės iš istream ir ostream.

Galima sukurti objektus, kurie nukreipia įvedimoišvedimo srautus išį failus. Jiems atitinkamai galioja operatoriai >> ir <<. Konstruktoriaus parametru yra failo vardas. Failo uždarymui naudojamas metodasclose().

#include #include main() {ofstream ofs (“Rez58.txt”);ifstream ifs (“Duom58.txt”);int A;ifs >> A;cout << ” A= ” << A << endl;ofs << A;ofs.close(); ifs.close(); }

Failų atidarymo rėžimaiRėžimas Aprašymasios::in Failas atidaromas skaitymuiios::out Failas atidaromas rašymuiios::ate Failas atidaromas rašymui, išvedimas pradedamas nuo failo galo (at end)ios::app Failas atidaromas papildymuiios::trunc Naikinamas failo turinysios::binary Failas atidaromas dvejatainiame režime

Pavyzdžiain ifstream (const char *name, ios::openmode = ios::in);n ofstream (const char *name, ios::openmode = ios::out | ios::trunc);n fstream (const char *name, ios::openmode = ios::in | ios::out);fstream fs(“File.dat”);

ofstream fs;fs.open(“File.dat”, ios::app);

if ( ! fs )cout<< “Failo nepavyko atidaryti”<> A; ?cout << A << endl;R << A << endl; } D.close(); R.close(); }

istream::get ifstream’e#include #include main() {ofstream R(“Rez511.txt”);ifstream D(“Duom511.txt”);char sim; while(!D.eof()) {sim = D.get(); // get() naudojamas, kaip istreamcout << sim;R << sim; }D.close();R.close();}

ios.fail()Kiekvienu skaitymo iš failo žingsniu būtina patikrinti, ar veiksmas buvo sėkmingai atliktas.

Tam skirtas metodas fail(), kurio rezultatas yra 0, kai klaidų nebuvo, ir 1, kuomet įvyko klaida.

Klaidų pranešimams ekrane skirtas išvedimo srautu objektas cerr.

Metodas fail() naudojamas išvedime, norint įsitikinti, ar veiksmas buvo sėkmingas.

#include #include main(){ofstream R (“Rez512.txt”);ifstream D (“Duom512.txt”);int a;if ( D.fail() ) cerr << “Neatidarytas duomenu failas”;else {while((!D.eof()) && (!D.fail())) {D >> a;if( ! D.fail() ) {R << a << endl;cout << a << endl; }}}D.close();R.close();}

ostream::write istream::read Šiose klasėse yra write ir read metodai, skirti duomenųmainams su failais baitų lygyje.

n write( const char* pointer, int nCount ); n read ( char* pointer, int nCount );

Struktūros (3 paskaita)

StruktūrosVisi kintamieji, iki šiol kuriais naudojotės, priklausė baziniamsC/C++ duomenų tipams: q Sveiko tipo (int) kintamieji ir konstantos;q Realaus tipo (float) kintamieji ir konstantos;q Dvigubo tikslumo (double) kintamieji ir konstantos;q Simbolinio tipo (char) kintamieji ir konstantos;Šie duomenys galėjo sudaryti masyvus, tačiau masyvo ele-mentais gali būti tik to paties bazinio tipo duomenys.

Struktūra – tai vienodo arba skirtingo tipo kintamųjų rinkinys. Struktūra priklauso išvestinių (vartotojo) duomenų tipui.

Struktūra realiame pasaulyjen Sąrašaiq Įmonės darbuotojain Vardas, pavardė, adresas, gim.metai, išsilavinimas, paso Nr.q Telefono numeriųn Vardas, pavardė, adresas, tel.Nr.n Kartotekosq Knygų, prekių, CD …

Struktūra realiame pasaulyjeElementas D. tipas Ilgis (eilutės) KomentarasID char * 4 Kodasname char * 20 Pavadinimas description char * 40 Aprašymas category int 12 Kategorijacost float Kaina number int Kiekis

Struktūros sintaksėstruct NAME { type1 var1; type2 var2; …… typeN varN;} ; // ; būtinas!!!!

struct CD {char name[20]; char description[40]; char category[12]; float cost; int number; } ;

Struktūrinis objektasstruct CD { char id[4]; char name[20]; char description[40]; char category[12]; float cost; int number; } disc;

CD disc, cdrom;CD disc[10],cdrom [100];CD *pointer;

struct CD disc; // C kalbos sintaksė

Struktūros elementų inicializacijastruct CD { char id[4]; char name[20]; char description[40]; char category[12]; float cost; int number; } disc = {“p12”, “Aliukai”,“Best Hists”,”pop-muzika”, 12.20, 12};

CD disc={“p12”, “Aliukai”,“Best Hists”,”pop-muzika”, 12.20, 12};

Struktūros elementų pasiekimasKreipiantis į struktūrų elementus vartojami sudėtiniai vardai:Struktūros_objekto_vardas.lauko_vardas

disc.cost=10.12;disc.number=9;strcpy(disc.id, “p12”);strcpy(disc.name, “Aliukai”);strcpy(disc.description, “Best Hits”);// kitas variantas cout<<“ Iveskite kieki : “; cin >>disc.number; cout<<“ Iveskite ID : “; cin.getline(disc.id, sizeof(disc.id));

Bitiniai laukaiSiekiant taupyti atmintį, struktūros elementams gali būti priskirti bitiniai laukai. Sintaksė:Lauko_deklaravimas : konstanta;

struct DATE { unsigned short Year; unsigned short Month; unsigned short Day;}

struct DATE{unsigned Year : 12;unsigned Month : 4;unsigned Day : 5;}

Struktūros – funkcijų argumentaistruct CD { char id[4]; char name[20]; char description[40]; char category[12]; float cost; int number; }

void func(CD); – funkcijos prototipas, kai struktūra argumentų sąrašeCD func1(СD); – funkcijos prototipas, kai struktūra argumentų sąraše ir grąžinama struktūra.

struct CD { char name[20]; char description[40]; char category[12]; float cost; int number; } disc, getdisc();void main() { disc=getdisc(); cout<”.

struct telefonas{ char vardas[30]; unsigned long tel_nr; };

struct telefonas Tel, *P, TelMas[100];P = &Tel;cout << P->tel_nr, Tel.vardas, P->vardas;

Junginiai (union)Junginiai (union) tai tam tikros struktūros, kurios naudojamos tuomet, kai norima toje pačioje atminties srityje patalpinti skirtingo tipo duomenis. Tam tikru laiko momentu atmintyje gali būti tik vienas iš apibrėžtų duomenų elementų.union Mydata{int var1; unsigned long frequency; char Symb[10];} myX = 25; // Reikšmė 25 priskiriama var1

Direktyvos, klasės (4 paskaita)

DirektyvosPriešprocesoriaus direktyvos – tai komandos kompiliatoriui, kurios leidžiavaldyti kompiliavimo procesą. Visos direktyvos pradedamos ženklu #. Direktyvos apdorojamos pirminiame programos kompiliavimo etape.

#include \ paieška include#include “header_name” \ paieška . po to include#include macro \ makro komandos prijungimas

#include #include “def.h”#include MACRO(x) ( (x)*(x) )

#define #undefDirektyva #define leidžia apibrėžti identifikatorių, o #undef jį naikina.

#define _cplusplus \ apibrėžia identifikatorių arba simbolinę konstantą#define WIDTH 80#define LENGTH ( WIDTH + 10 ) \ LENGHT = 90 ..#undef WIDTH #undef LENGTH

#ifdef #ifndef Direktyvos #ifdef ir #ifndef tikrina ar identifikatorius yra/nėraapibrėžtas. Jis veikia kaip sąlygos operatorius, todėl

užbaigiamas #endif direktyva.

#ifndef test #define final #endif

#if, #elif, #else, #endif #if direktyva kartus su #elif, #else ir #endif direktyvomis, kontroliuoja kompiliavimą tam tikrų programos dalių. Jei išraiška, kuri parašyta po #if turi nenulinę reikšmę, eilučių grupė, einanti tuoj pat po #if direktyvos siunčiama transliavimo vienetui.#if defined(CREDIT) credit(); #elif defined(DEBIT) debit(); #else printerror(); #endif

#if DLEVEL > 5 #define SIGNAL 1#if STACKUSE == 1 #define STACK 200 #else #define STACK 100 #endif #else #define SIGNAL 0 #if STACKUSE == 1 #define STACK 100#else #define STACK 50#endif #endif

Direktyvų panaudojimo pavyzdys// EXAMPLE.H – header file

#if !defined( EXAMPLE_H ) #define EXAMPLE_H class Example { … }; ..#endif

MacrosMacros – tai programinio kodo fragmentas, kuris atrodo ir elgiasi kaip funkcija, tačiau egzistuoja tokie skirtumai:

q Macros naudojamas priešprocesoriuje, prieš pradedant kompiliavimąq Macros dirba greičiau nei funkcija, nors ir padidina programos ilgį.q Macros’e netikrinami kintamųjų tipaiq Neįmanoma nustatyti nuorodą į macros, nes tai programos dalisMacros pavyzdys#include #define MULTIPY(x,y) ((x)*(y))

int main(){ int a=2, b=3; cout<< “Sandauga ”<char *Date = __DATE__;char *Time = __TIME__;

int main(){ cout<<“Failo sukurimo data ”<using namespace std;class small { private: int somedata; public: void setdata(int d){somedata = d; } void showdata(){cout<<“Duomenys “< }

Pavyzdysint AnyClass::get_a(){return a;}

void AnyClass::set_a(int num){a = num;}

Klasės elementų požymiaiKlasės elementai (duomenys ir metodai) gali turėti požymius. Požymis klasėje galioja tol, kol bus sutiktas kito požymio užrašas. Jeigu požymio užrašo nėra, tuomet pagal nutylėjimą bus priimtas private visiems elementams iki pirmojo požymio užrašo, jeigu jis bus. Yra tokie požymiai:n private (lokalusis). Duomenys ir metodai prieinami tik klasės metodams.n public (globalusis). Klasės elementai prieinami tiek klasės funkcijoms tiek ir išorinėms funkcijoms.n protected (apsaugotasis). Klasės elementai prienami klasėje, kuri paveldi duotąją klasę. Paveldėtoje klasėje jie galioja private teisėmis

PalyginimasSavybės Klasės Struktūros JunginiaiRaktinis žodis class struct UnionPriėjimas prie duo-menų (default) private public PublicDuomenų perdengimas ne ne taipKlasės savybėsn Klasės duomenų apribojimai:q Klasės duomenys negali būti apibrėžiami, naudojant modifikatorius auto, extern ir register;q Klasės duomenų tarpe negali būti tos pačios klasės objektas, tačiau gali būti nuoroda į objektą ar kitos klasės objektas.n Paprastai duomenys būna private, o funkcijos public.n Klasė formuoja savo vardų erdvę, todėl kreiptis į kintamąjį iš kitos klasės galima naudojant tokią sintaksę:

klasės_vardas::kintamojo_ar_funkcijos vardasPavyzdys#include // Klasės aprašymasclass Studentas { char *pav; float svoris;public: void Skaito() { cout << “Iveskite pavarde: n”;cin >> pav;cout << “Iveskite svori:n”;cin >> svoris; };void Rodo() { cout << pav << ” ” << svoris << endl; };};

// Pagrindinė programavoid main() {Studentas A, B; A.Skaito();B.Skaito();B.Rodo();A.Rodo();}

Konstruktorius, destruktorius, draugiškos funkcijos (5 paskaita)KonstruktoriusSukuriant objektą, jo duomenims paprastai priskiriamos pradinės reikšmės. Tai gali atlikti tam skirti metodai. Bet būtų patogu, jei kuriant objektą, duomenų inicializacija būtų atliekama automatiškai, neiškviečiant papildomų funkcijų. Tai galima atlikti naudojant specialų metodą – konstruktorių. Konstruktorius – tai metodas, kuris automatiškai vykdomas kiekvieną kartą, kai tik sukuriamas objektas. Konstruktorius turi tokį pat pavadinimą, kaip ir klasė bei nieko negrąžina. Jo paskirtis – priskirti pradines reikšmes klasės kintamiesiems.#include class studentas{ float svoris;public: studentas(float x) { svoris = x; } void rodo() { cout << svoris << endl; }};void main(){ studentas Algis(120.25); studentas Jonas(56.2); cout<<“Algio svoris “<class Counter{ unsigned int count;public: count() { count = 0; } void increase() { cout ++ ; } int show() { return count; }};

void main(){ Counter C1; cout<<“Skaitliukas = “<< C1.show() << endl;C1.increase(); cout <<“Skaitliukas =“ << C1.show()<class Any{ int a, b;public: Any(int x, int y) { a = x; b = y; } void show_x() { cout << x< Obj.name(&Obj, par1, par2); Obj::name(param1, param2) { cout<<“Hello”<param1<>ilgis>>plotis;}};

Objektų masyvaiObjektai kaip ir paprasti kintamieji gali sudaryti masyvus. Sintaksė niekuo nesiskiria nuo įpratinės masyvų apibrėžimo sintaksės.AnyClass ACDC[10];Kompiliatorius kurdamas masyvą, naudoja konstruktorių pagal nutylėjimą, todėl rekomenduojama klasėje apibrėžti tokį konstrukorių. Masyvų elementai pasiekiami analogiškai, kaip ir įprastinių masyvų.

class AnyClass{ int a; public:AnyClass(int x) { a = x; } int show() { retunt a; }};

main(){ AnyClass Arr[3] = { 12, 14, 16};for (int i = 0; i<3; i++) cout<< Arr[i].show()<< endl; return 0; }

class AnyClass{ int x, y; public:AnyClass(int a, int b) { x=a, y=b; } int Getx() { return x; }int Gety() { return y; }};

main ()AnyClass Arr[2][2] = { AnyClass(1,2), AnyClass(2,3), AnyClass(3,4), AnyClass(5,6)};int i , j;for (i = 0; i<2; i++)for (j = 0; j<2; i++) { cout<< Arr[i][j].Getx()<< endl; cout<< Arr[i][j].Gety()<< endl;} return 0; }

class AnyClass{ int x, y; public:AnyClass(int a, int b) { x=a, y=b; } AnyClass() { x=0, y=0; } // konstruktorius pagal nutylėjimąint Getx() { return x; }int Gety() { return y; }};main ()AnyClass * ptr;int i ;ptr = new AnyClass[6];for (i = 0; i<6; i++) { cout<< ptr->Getx()<< endl; cout<< ptr->Gety()<< endl; ptr ++; } return 0; }

Draugiškos funkcijos C++ leidžia apeiti vieną iš pagrindinių OOP savybių t.y. duomenų inkapsuliaciją panaudojant draugiškas funkcijas ir draugiškas klases. Paprastai uždari klasės duomenys, pasiekiami per tos pačios klasės metodus. Tačiau klasės duomenis galima pasiekti ir per išorinę draugišką funkciją. Ta pati funkcija gali turėti priėjimą prie kelių klasių duomenų. Tokia funkcija turi būti apibrėžta klasėje su atributu friend.class beta;class alfa{ int data; public: alfa() : data(3) { } friend int draugas (alfa, beta) // draugiška funkcija};class beta{ int data; public: alfa() : data(7) { } friend int draugas (alfa, beta) // draugiška funkcija};int draugas (alfa a, beta b){ return (a.data + b.data);}main () alfa aa; beta bb; cout<< draugas(aa, bb)<< endl; return 0; }

Draugiškos klasės, paveldėjimas (6 paskaita)Draugiškos funkcijos Draugiškos funkcijos nepriklauso klasės metodams, todėl iškviečiant draugišką funkciją, nereikia prieš ją nurodyti objekto vardo ar nuorodos į objektą. Uždarus klasės duomenis draugiška funkcija pasiekia per klasės objektą, kuris turi būti apibrėžtas funkcijoje arba perduotas per funkcijos argumentų sąrašą.Draugiška funkcija nepaveldima.

class AnyClass{ int n, d; public: AnyClass (int x, int y) : n(x), d(y) { } friend bool draugas (AnyClass) ; }; bool draugas (AnyClass obj){ if (! obj.n % obj.d ) return true; return false; }

main () AnyClass obj (12, 3); if (draugas(obj)) cout<< “12 dalinasi is 3”<< endl; else cout<< “12 nesidalina is 3”<< endl; return 0; }

Funkcija gali būti vienos klasės metodu, o kitoje klasėje būti draugiška funkcija.class beta; // nepilnas klasės apibrėžimas. Jis būtinasclass alfa{ int data1, data2, ; public: alfa() : data1(3), data2(4) { } int draugas (beta bb) { return (bb.b1 + bb.b2); }};class beta{ int b1, b2; public: beta() : b1(7) b2(8) { } friend int alfa::draugas (beta bb) // draugiška funkcija iš klasės alfa};void main () { alfa aa; beta bb; cout<< aa.draugas(bb)<< endl; }

Draugiška klasėC++ leidžia apibrėžti ne tik draugiškas funkcijas, bet ir klases. Draugiškai klasei suteikiamos teisės pilnai naudoti duotosios klasės duomenimis. Tam tikslui reikia, kad klasėje A būtų skelbiama, kad klasė B yra draugiška. Tai daroma parašant atributą friend prieš klasę. Draugiška klasė skelbiama klasės dalyje public.

Taisyklės, taikomos draugiškoms klasėms:§ Negalioja abipusės draugystės savybė t.y. jei klasė B yra draugiška klasei A, tai nereiškia, kad klasė A draugiška klasei B.§ Draugiškos klasės nepaveldimos. Jei klasė B yra draugiška klasei A, tai klasėse, kurios yra gautos, kaip B išvestinės, nėra draugiškos klasei A. § Draugiškumas nepaveldimas t.y. jei B yra draugiška klasei A, tai klasėse kurios yra gautos, kaip A išvestinės, klasė B nėra draugiška.

class A{ int n, d; public: A (int x, int y) { n=x; d=y; } void increase() { n++; d = d*10; } friend class B ; };class B{ A objA; public: void show() { cout<< “Pradinės reikšmės”<#include // Klasė Pirmas class Pirmas { int x; public: Pirmas(int a) { x = a; } void Rodo(){ printf(“Pirmas::rodo() %5d nr”, x); }};// Klasė Antras class Antras: public Pirmas { int y; public: Antras(int b, int c) : Pirmas(5) { y = c; } void Rodo(){ printf(“Antras::rodo() %5d nr”, y); }};

main (){ Antras B (4, 55); B.Rodo(); B.Pirmas::Rodo();}

DestruktoriusNors destruktorius nėra paveldimas, uždarinėjant išvestinės klasės objektą, vistiek įvykdomas bazinės klasės destruktorius.Išvestinės klasės destruktorius turi būti vykdomas ankščiau nei bazinės, priešingu atveju bus sunaikinti bazinės klasės duomenys.Destruktoriaus vykdymo eiliškumu rūpinasi kompiliatorius t.y. programuotojo tai neliečia.class Base{ public: Base() { cout << Bazinis konstruktorius<// funkcijos abs perkrovimasint abs (int a);float abs (float b);double abs (double c);void main (){ int x = 255; float y = -1.2f; double z = -15.0; cout << abs (x)<< endl; cout << abs (y)<< endl; cout << abs (z)<< endl; }

int abs (int a){ return a<0? –a:a; }

float abs (float b){ return b<0? –b:b; }

Funkcijų perkrovimo apribojimain Perkraunamos funkcijos turi turėti skirtingus argumentų sąrašus;n Negalimos perkrautos funkcijos, turinčios tuos pačius argumentų sąrašus ir skirtis tik grąžinamos reikšmės tipu.n Klasės metodai nelaikomi perkrautais, jei vienas iš jų apibrėžtas kaip static, o kitas ne.n typedef operatorius neįtakoja perkrovimo mechanizmui.

typedef char* ptr;void SetVal (char * xx); Klaida, tai nepersidengiančios funkcijosvoid SetVal (ptr xx);

Klasės metodų perkrovimo pavyzdysclass Lapas { int x; float y; char z; public: Lapas (int, float, char ) { x = A; y = B; z = C; } // Konstruktorius Lapas() { x = 0; y = 0; z = ‘z’; } // Konstruktorius void Rodo (char *); void Suma (int Sk) { x = x + Sk; } void Suma (float Sk) { y = y + Sk; } void Suma (char Sk) { z = Sk; } void Suma (int A, char B) { x = x + 2.0 * A; z = B + 4; }};void Lapas::Rodo(char *Eilute) {cout << Eilute << ” : “;cout << ” x= ” << x << ” y= ” << y << ” z= ” << z < Func(104); //blogai ptr -> Func(12.2, “Eilute”) return 0;};

Konstruktorių perkrovimasDažniausiai perkrovimas naudojamas kuriant perkrautus konstruktorius. Taip yra daroma siekiant suteikti galimybę kurti objektus, naudojant skirtingus argumentų sąrašus.Class Rect{ private : int x,y,w,h; public: Rect() {x=y=w=h=0; } Rect(int a, int b); { x = a; y = b; w=h=10; } Rect(int a, int b, int c, int d); { x = a; y = b; w = c; h=d; } Rect(const Rect&); Rect(const Rect&, int, int );};Rect::Rect(const Rect& rc){x=rc.x; y=rc.y; w = rc.w; h = rc.h }

Konstruktorių perkrovimasRect::Rect( const Rect& rc, int _x, int _y){x = _x; y = _y; w= rc.w; h = rc.h;}void main (){ Rect rc(3,4,5,6); Rect newrc(rc, 14, 34);}Kopijos konstruktoriusKopijos konstruktorius naudojamas siekiant jau iš esamo objekto sukurti naują, kaip esamo kopiją. Kintamųjų kopijos daromos, kai jie perduodami funkcijoms per argumentų sąrašą. Dėl tos priežasties C++ buvo sukurtas kopijos konstruktorius, kuris automatiškai generuojamas kuriant objektus.Tokiu būdu panaudojant panaudojant tokią sintaksę:

AnyClass obj1;Anyclass obj2(obj1); atliekamas objekto kopijavimas.Argumentų sąraše naudojant rodykles į objektą, turime reikalą su tuo pačiu objektu o ne jo kopija.Perkrovimas ir nevienareikšmiškumas Kompiliatorius funkcijas išrenka pagal geriausio atitikimo principą t.y.1. Rasta tikslaus pavadinimo f-ja;2. Rasta tikslių argumentų f-ja;Jei po tokios atrankos, lieka daugiau nei viena funkcija, kompiliatorius generuoja klaidą ir perkrovimas laikomas neveinareikšmiu.Norint valdyti perkrautų konstruktorių paiešką, C++ turi dar vieną galimybę t.y. explicit identifikatorių panaudojimą. Toks identifikatorius neleidžia konstruktoriui atlikti neištrikštinį duomenų keitimą

class T{ public: explicit T(int); explicit T(double);};

Perkrautos f-jos adresasFunkcijos adresas randamas tokiu būdu: rodyklei, kurios tipas atitinka funkcijos tipą priskiriamas funkcijos, kurios adresas ieškomas be argumentų sąrašo.Turint perkrautas funkcijas atranka atliekama pagal bendras taisykles.Pavyzdys:int Func(int i, int j);int Func(long l);int (*ptr)( int, int) = Func;pFunc(10,20);

Operatorių perdengimasProgramavimo kalbose naudojami operatoriai pasižymi polimorfizmu(daugiavariantiškumu). Kaip pavyzdys gali būti operatorius +, kuristaikomas tiek int, tiek float tipo kintamiesiems, nors sudėtiesveiksmai procesoriaus registruose atliekami nevienodai.Klasėse galima naujai apibrėžti operatorius, t.y. pakeisti jų veikimą. Toksnaujas operatorių perorientavimas yra vadinamas perdengimu.Operatorių aprašai nuo funkcijų skiriasi vartojamu žodžiu operator. Operatoriaus perdengimo sintaksė : operator ;

Perdengimas draudžiamas operatoriams: . .* :: ?:

Operatorių perdengimas gali galioti lokaliai t.y. klasės ribose arba globaliai t.y. visoje programoje.Operatoriai – tai funkcijos, todėl operatorių perkrovimas siejamas su funkcijų perkrovimu.class Katinas { public:Katinas(char *);

void operator + (char *);void operator – (char );void Rodo();~Katinas(); private:char *Vardas;};

Katinas::Katinas(char *Vardas) {Katinas::Vardas = new char[N];strcpy(Katinas::Vardas, Vardas); } void Katinas::Rodo(){ cout << Vardas << endl; }void Katinas::operator + (char * A){ strcat(Vardas, A); }void Katinas::operator – (char C) { for(int i=0; *(Vardas+i) != ‘’; ) { if(*(Vardas + i) == C)for(int j=i; j<(strlen(Vardas)-1); j++)*(Vardas + j) = *(Vardas + j+1);i++;}}

Katinas::~Katinas(){ delete Vardas; }

// Pagrindinė programavoid main(void) {Katinas A (“Batuotas ir piktas”);A.Rodo();A + ” Rudas! “;A.Rodo();A – ‘a’;A.Rodo();getch();

Operatorių perkrovimas (8 paskaita)Operatorių perdengimas

Programavimo kalbose naudojami operatoriai pasižymi polimorfizmu(daugiavariantiškumu). Kaip pavyzdys gali būti operatorius +, kuristaikomas tiek int, tiek float tipo kintamiesiems, nors sudėtiesveiksmai procesoriaus registruose atliekami nevienodai.Klasėse galima naujai apibrėžti operatorius, t.y. pakeisti jų veikimą. Toksnaujas operatorių perorientavimas yra vadinamas perdengimu (perkrovimu).Operatorių aprašai nuo funkcijų skiriasi vartojamu žodžiu operator. Operatoriaus perdengimo sintaksė : [tipas] operator (parametrai);

Perdengimas draudžiamas operatoriams: . .* :: ?:

Operatorių perdengimas gali galioti lokaliai t.y. klasės ribose arba globaliai t.y. visoje programoje.Operatoriai – tai funkcijos, todėl operatorių perkrovimas siejamas su funkcijų perkrovimu.class Katinas { public:Katinas(char *); void operator + (char *);void operator – (char );void Rodo();~Katinas(); private:char *Vardas;};

Katinas::Katinas(char *Vardas) { Katinas::Vardas = new char[N]; strcpy(Katinas::Vardas, Vardas); } void Katinas::Rodo() { cout << Vardas << endl; } void Katinas::operator + (char * A) { strcat(Vardas, A); } void Katinas::operator – (char C) { for(int i=0; *(Vardas+i) != ‘’; ) { if(*(Vardas + i) == C) for(int j=i; j<(strlen(Vardas)-1); j++) *(Vardas + j) = *(Vardas + j+1); i++; } }

Katinas::~Katinas(){ delete Vardas; }

// Pagrindinė programavoid main(void) {Katinas A (“Batuotas ir piktas”);A.Rodo();A + ” Rudas! “;A.Rodo();A – ‘a’;A.Rodo();getch();

Perdengiami operatoriaiOperatorių perdengimas – tai funkcijos operatoriai, kurių pavadinimai siejami su raktiniu žodžiu operator ir po juo einančiu operatoriumi.Taisyklė:Funkcijos-operatoriai turi būti nestatiniai klasės metodai arba turėti klasės tipo argumentą arba nuorodą į klasę. Sintaksė:Binariniai operatoriai [tipas] operator (par1); (lokalus) [tipas] operator (par1, par2); (globalus)Unariniai operatoriai [tipas] operator (); (lokalus) [tipas] operator (par1); (globalus)Unary: + – * ! ~ & ++ — () -> ->*

new delete Binary: + – * / % & | ^ << >> = += -= /= %= &= |= ^= <<= >>= == != < > <= >= && || [] () ,

Pavyzdys (lokalus perdengimas)class Point {public:Point (int x, int y) {Point::x = x; Point::y = y;}Point operator + (Point &p) {return Point(x + p.x, y + p.y);}Point operator – (Point &p) {return Point(x – p.x, y – p.y);}private:int x, y;};

void main () {Point p1(10,20), p2(10,20);Point p3 = p1 + p2;Point p4 = p1 – p2;}

Pavyzdys (globalus perdengimas)class Point {public:Point (int x, int y) {Point::x = x; Point::y = y;}friend Point operator + (Point &p, Point &q) //globalus operatrorius{return Point(p.x + q.x,p.y + q.y);}friend Point operator – (Point &p, Point &q) {return Point(p.x – q.x,p.y – q.y);}private:int x, y;};

Perkrauto operatoriaus naudojimas – ekvivalentiškas funkcijos iškvietimui. Pavyzdžiui:operator+(p1, p2); // tas pats: p1 + p2Pavyzdysclass Point {//…Point (int x) { Point::x = Point::y = x; }friend Point operator + (Point, Point);};

Naudojamas vieno argumento konstruktorius:

Point p = 10; // equivalent to: Point p(10);

Objektai būtų kuriami taip:

Point p(10,20), q = 0;q = p + 5; // equivalent to: q = p + Point(5);

Operatoriaus << perdengimas Operatoriaus << perdengimas leidžia efektyviai naudoti išvedimo procedūra.

class Binary {//…friend ostream& operator << (ostream&, Binary&);};ostream& operator << (ostream &os, Binary &n){char str[binSize + 1];strncpy(str, n.bits, binSize);str[binSize] = ‘’;cout << str;return os;}Binary n1 = “01011”, n2 = “11010”;cout << n1 << ” + ” << n1 << ” = ” << n1 + n2 << ‘n’;

Pirmas parametras – tai nuoroda į ostream, antras – nuoroda, kuri bus modifikuojama

Operatoriaus >> perdengimasclass Binary {//…friend istream& operator >> (istream&, Binary&);};istream& operator >> (istream &is, Binary &n){char str[binSize + 1];cin >> str; n = Binary(str); // use the constructor for simplicityreturn is;}Įvedimas main() funkcijoje atrodytų: Binary n; cin >> n;Pirmas parametras – tai nuoroda į istream, antras – nuoroda, kuri bus modifikuojama

[ ] perkrovimas# Kuriamas asociatyvinis masyvas#include #include class AssocVec {public:AssocVec (const int dim);~AssocVec (void);int& operator [] (const char *idx);private:struct VecElem {char *index;int value;} *elems; // vector elementsint dim; // vector dimensionint used; // elements used so far};

AssocVec::AssocVec (const int dim){AssocVec::dim = dim;used = 0;elems = new VecElem[dim];}AssocVec::~AssocVec (void){for (register i = 0; i < used; ++i)delete elems[i].index;delete [] elems;}

int& AssocVec::operator [ ] (const char *idx){for (register i = 0; i < used; ++i) // search existing elementsif (strcmp(idx,elems[i].index) == 0)return elems[i].value;if (used < dim && // create new element (elems[used].index = new char[strlen(idx)+1]) != 0) {strcpy(elems[used].index,idx);elems[used].value = used + 1;return elems[used++].value;}static int dummy = 0;return dummy;}Naudojame perkrautą [ ] taip:AssocVec count(5);count[“apple”] = 5;count[“orange”] = 10;count[“fruit”] = count[“apple”] + count[“orange”];Atsakymas: count[“fruit”] to 15.

new ir delete perdengimasDinaminio atminties paskirstymo operatoriai new ir delete gali būti perkrauti klasėse. Toks perkrovimas susijęs su racionalesniu atminties panaudojimu.#include #include const int maxPoints = 512;class Point {public://…void* operator new (size_t bytes);void operator delete (void *ptr, size_t bytes);private:int xVal, yVal;static union Block {int xy[2];Block *next; } *blocks; // points to our freestorestatic Block *freeList; // free-list of linked blocksstatic int used; // blocks used so far};

Point::Block *Point::blocks = new Block[maxPoints];Point::Block *Point::freeList = 0;int Point::used = 0;

void* Point::operator new (size_t bytes){Block *res = freeList;return used < maxPoints ? &(blocks[used++]) : (res == 0 ? 0 : (freeList = freeList->next, res));}void Point::operator delete (void *ptr, size_t bytes){((Block*) ptr)->next = freeList;freeList = (Block*) ptr;}

Funkcijoje main() panaudojimas:

Point *pt = new Point(1,1);// calls Point::operator newchar *str = new char[10]; // calls ::operator newdelete pt; // calls Point::operator deletedelete str;// calls ::operator delete

Operatorių++ ir — perdengimasclass coord{ int x,y;public: coord() {x=0; y=0} coord(int _x = x; int _y=y;}void Getcoord(int& _x, int& _y) { _x=x; _y=y;}coord& operator++(); //prefixcoord& operator++(int);//sufixcoord& operator–(); //prefixcoord& operator–(); //sufix};coord& coord::operator++(){ x++; y++; return *this;}

coord& coord::operator++(int){coord temp = *this; ++ *this; return temp;}coord& coord::operator–(){ x–; y–; return *this;}coord& coord::operator–(int){coord temp = *this; — *this; return temp;}

void main(){ int x,y; coord pta(10,20), ptb(15,25), ptc; ++pta;pta.Getcoord(x,y);

cout << x << “ “<< y<< endl; pta–;pta.Getcoord(x,y);cout << x << “ “<< y<< endl; ptc = ptb++;ptc.Getcoord(x,y);cout << x << “ “<< y<< endl; ptb.Getcoord(x,y);cout << x << “ “<< y<< endl; }

Polimorfizmas ir virtualios funkcijos (9 paskaita)Kam reikalingos virtualios funkcijos?C++ virtualumas suprantamas, kaip polimorfizmo ir paveldėjimo savybių apjungimas.Iki šiol nagrinėtos perkrautos funkcijos ar operatoriai buvo nesiejami su klasių herarchija. Virtualios funkcijos naudojamos tuomet, kai tuo pačiu pavadinimu egzistuoja funkcijos tiek bazinėje tiek ir išvestinėse klasėse.Virtuali – reiškia neegzistuojanti realybėje, o tai suprantama, kad kviečiant funkciją iš vienos klasės, realiai vykdoma kitoje klasėje esanti funkcija.

Pavyzdys:shape* ptr_array [100];// 100 rodyklių masyvasfor (int i=0; i draw( ); // ta pati funkcija draw() kviečiama iš skirtingų objektų

Problema…nr.1BankAccount bretta; // base-class object Overdraft ophelia; // derived-class object bretta.ViewAcct();// use BankAccount::ViewAcct() }Vienareikšmiš-kai apibrėžtaophelia.ViewAcct(); // use Overdraft::ViewAcct() }

BankAccount bretta; BankAccount * bp = &bretta; // points to BankAccount object bp->ViewAcct();// use BankAccount::ViewAcct()bp = &ophelia;// BankAccount pointer to Overdraft object bp->ViewAcct(); // which version of ViewAcc? /atsakymasPagal nutylėjimą, C++ naudoja rodyklės arba nuorodos tipą, kad nuspręstų, kokią f-ją pasirinkti. Todėl bus naudojama BankAccount::ViewAcct()

Problema…nr.2Tačiau kompiliatorius kompiliavimo metu dažnai nežino, su kokiu objektu bus surišta nuoroda ar rodyklė.cout << “Enter 1 for Brass Account, 2 for Brass Plus Account: “;int kind; cin >> kind; BankAccount * bp; if (kind == 1) bp = new BankAccount; else if (kind == 2) bp = new Overdraft; bp->ViewAcct(); // neaišku, kuri funkcija bus iškviesta

ApibrėžimaiJei programos kompiliavimo metu, kompiliatorius pririša rodyklę ar nuorodą prie konkretaus objekto ir taip nustato, kurią iš perkrautų funkcijų naudoti, toks pririšimas vadinamas ankstyvuoju (early binding) arba statiniu (static binding). Kartais dar sakoma, jog tai statinio polimorfizmo atvejis.// static bindingBankAccount *bp;Overdraft ophelia; bp = &ophelia; // BankAccount pointer to Overdraft object bp->ViewAcct(); // use BankAccount::ViewAcct()

Jei programos kompiliavimo metu, kompiliatorius nepririša rodyklės ar nuorodos prie konktetaus objekto ir palieka galimybę programos vykdymo metu nuspęsti, kurio objekto metodą iškviesti, toks atvejis vadinamas vėlyvuoju (late binding) arba dinaminiu pririšimu (dynamic binding). Sakoma, jog turime dinaminio polimorfizmo atvejį.

Dinaminio pririšimo (dynamic binding) aktyvizavimasDinaminis pririšimas aktyvizuojamas tik klasės metodams. Norint tai atlikti bazinėje funkcijoje perkrauta funkcija apibrėžiama kaip virtuali (naudojamas raktinis žodis virtual).Jei metodas apibrėžtas kaip virtualus, jis toks išlieka visose paveldėtose (išvestinėse) klasėse. Vienam virtualiam metodui raktinis žodis naudojamas tik vieną kartą ir tik bazinėje klasėjePavyzdys// bankacct.h – a simple BankAccount class with virtual functions #ifndef _BANKACCT_H_ #define _BANKACCT_H_

class BankAccount { private: enum {MAX = 35}; char fullName[MAX]; long acctNum; double balance; public: BankAccount (const char *s = “Nullbody”, long an = -1, double bal = 0.0); void Deposit (double amt); virtual void Withdraw (double amt);// virtual methoddouble Balance() const; virtual void ViewAcct() const;// virtual method }; class Overdraft : public BankAccount { private: double maxLoan; double rate; double owesBank;public: Overdraft (const char *s = “Nullbody”, long an = -1, double bal = 0.0, double ml = 500, double r = 0.10); Overdraft (const BankAccount & ba, double ml = 500, double r = 0.1); void ViewAcct()const; void Withdraw(double amt); void ResetMax(double m) { maxLoan = m; } void ResetRate(double r) { rate = r; }; void ResetOwes() { owesBank = 0; } }; #endif int main() { BankAccount * baps[ASIZE]; char name[MAX]; long acctNum; double balance; int acctType; for (int i = 0; i < ASIZE; i++) {// su cin >> nuskaitomi name, acctNum, balance, acctTypeif (acctType == 2) baps[i] = new Overdraft(name, acctNum, balance); else { baps[i] = new BankAccount(name, acctNum, balance); if (acctType != 1) cout << “I’ll interpret that as a 1.n”; } } for (i = 0; i < ASIZE; i++) { baps[i]->ViewAcct(); cout << endl; } return 0; }

Kodėl naudojamos du polimorfizmo tipai?Dinaminis polimorfizmas leidžia pakeisti klasės metodus – tai patogu kuriant didelius programinius projektus (>1000 eilučių). Statinis polimorfizmo naudojimas duoda didesni programos vykdymo efektyvumą. Programos vykdymo metu nevykdomas funkcijų apibrėžimas iš naujo bei jų atranka, taip taupomas programos vykdymo laikas.

Taisyklės:• Virtualios funkcijos naudojamos tose paveldimose klasėse, kur reikalingas funkcijų apibrėžimas iš naujo.• Statinės funkcijos negali būti apibrėžtos virtualiomis.• Virtuali funkcijos prototipas visose klasėse turi būti identiškas t.y. sutapti parametrų sąrašas bei grąžinamos reikšmės tipas.

Virtualios ir nevirtualios funkcijos pavyzdys#include class Base{ public: virtual void VirtFunc() { cout << “Base::VirtFunc()n”; } void show(){cout << “Base klases funkcija n”; }};class Derived: public Base{ public: void VirtFunc(){ cout << “Derived::VirtFunc()n”; } void show(){ cout << Derived klases funkcija n”;}};

void main (){Derived A_isvestine; Derived *ptr_isvestine; Base *ptr_base = &A_isvestine; ptr_base->VirtFunc(); // virtualios funkcijos iškvietimas ptr_base->show();// nevirtuali funkcija

ptr_isvestine->VirtFunc();// virtualios funkcijos iškvietimas ptr_isvestine->show();// nevirtuali funkcija}

Virtualus destruktoriusKonstruktoriai negali būti virtualūs, tačiau destruktoriai gali. Kai šalinamas išvestinės klasės objektas, o destruktorius yra apibrėžtas kaip virtualus, vykdomi tiek išvestinės tiek ir bazinės klasės destruktoriai. Priešingu atveju iškviečiamas tik išvestinės klasės destruktorius ir atmintyje lieka nepanaikinti bazinio objekto duomenys.

class Base{ public: ~Base()// virtual ~Base() taip turėtų būti{cout<< “Base destroyed n”; }};class Derived: public Base{public: ~Derv() {cout<< “Derived destroyed n”; }};

Daugybinis paveldėjimas, virtualios bazinės klasėsSiekiant išvengti dvigubo bazinės klasės įtraukimo, naudojamos virtualios bazinės klasės. Tam prieš paveldimumo identifikatorių rašomas žodis virtual. class IndBase{ int x; public: int GetX() {return x; } void setX (int _x) { x= _x ;} double var; };Class Base1: virtual public Indbase { …. };Class Base2: public virtual Indbase { …. };

Class Derived: public Base1, public Base2 { …. };

main () Derived ob; ob.var = 5.0 ob.SetX(0); int z = ob.GetX(); return 0; }

Abstrakčios klasės ir pure virtual funkcijosEgzistuoja klasės, kurios nėra naudojamos objektams kurti, o tik tam, kad sudarytų reikiamą klasių herarchijos medį ir užtikrintų logišką paveldimumą. Tokios klasės vadinamos abstrakčiomis (abstarct).Pavyzdžiui: bazinė klasė shape ir klasės trikampis, apskritimas, keturkampis ir t.t Akstrakti klasė turi bent vieną virtualią funkciją, o tiksliau tikrą virtualią (pure virtual). Išvestinės klasės turi būtinai panaudoti abstrakčios klasės virtualias funkcijas, priešingu atveju jos taip pat tampa abstrakčiomis (dėl paveldimumo).Tikrai virtualia funkcija vienareikšmiškai pasako, kad klasė, kuriai ji priklauso yra abstrakti ir objektas iš tokios klasės negali būti sukurtas.

Tikrai virutalios funkcijos sintakse:virtual (argumentai) = 0;

Pure virtual funkcijos pavyzdysclass Base{ int x; public: Base( int xx) {x = xx;} virtual int GetX() {return x;} virtual void PrintX () = 0;};class Derived: public Base{ public: Derv(int xx): Base (xx); int GetX() { return 0;} void PrintX() {cout<< “x= “ <void main( int argc, char *argv[ ],char **envp )

{ int count; printf ( “nCommand-line arguments:” ); for( count = 0; count < argc; count++ ) printf( ” argv[%d] %sn”, count, argv[count] ); printf( “nEnvironment variables:” ); while ( *envp != NULL ) printf( ” %sn”, *(envp++) ); return;} Command-line arguments: argv[0] C:MSCTEST.EXE Environment variables: COMSPEC=C:NTSYSTEM32CMD.EXE PATH=c:nt;c:binb;c:binr;c:ntsystem32;c:word;c:helpTEMP=c:tmp TMP=c:tmp

Laiko skaičiavimas, naudojant time.h/* DIFFTIME.C: This program calculates the amount of time * needed to do a floating-point multiply 10 million times. */#include #include #include void main( void ){ time_t start, finish; long loop; double result, elapsed_time; printf( “Multiplying 2 floating point numbers 10 million times…n” ); time( &start ); for( loop = 0; loop < 10000000; loop++ ) result = 3.63 * 5.27; time( &finish ); elapsed_time = difftime( finish, start ); printf( “nProgram takes %6.0f seconds.n”, elapsed_time );}time_t structure contains the number of seconds since 00:00:00 UTC, January 1, 1970

Laiko skaičiavimas su MFC#include CTime startTime = CTime::GetCurrentTime();// … perform time-consuming task …CTime endTime = CTime::GetCurrentTime();CTimeSpan elapsedTime = endTime – startTime;

Ctime – MFC klasėCTimeSpan – MFC klasė

Kodėl šablonai (templates)n Šablonai leidžia sukurti bendro pobūdžio funkcijas ir klases, neprisirišant prie konkrečių duomenų tipų.n Leidžia kurti bendro tipo bibliotekas (STL) ir taip užtikrina daugkartinį funkcijų ar klasių panaudojimą.n Šablonų tipai : funkcijų, klasiųPavyzdys:int abs (int n){return (n<0) ? –n : n;}C kalboje egzistuoja fabs(), fabsl (), labs(), cabs()…

Funkcijų šablonai (function template)Funkcijos šablonas visad apibrėžiamas raktiniu žodžiu template ir vienu ar keliais prametrais .

template Max (T, T);

template T abs(T n){return (n<0)? –n, n;}

Argumentai, esantys <> viduje vadinami šablono argumentais. class – raktinis žodis. Jis būtinas prieš kiekvieną argumentą.

Kompiliatorius kuria konkrečią funkcijos realizaciją (šabloninę funkciją – template function) programos vykdymo metu.Kaip atrodys konkreti funkcija, priklauso nuo argumentų tipo.

Funkcijų šablonai su keletu argumentųtemplate T3 Relation(T1, T2);// oktemplate int Compare (T1, T1);// illegal! T2 not used.template // illegal! class missing for T2int Compare (T1, T2);

Pavyzdžiuitemplate T Max (T val1, T val2){return val1 > val2 ? val1 : val2;} cout << Max(19, 5) << ‘ ‘ << Max(10.5, 20.3) << ‘ ‘ << Max(‘a’,’b’) << ‘n’

Pavyzdystemplate int find(atype* array, atype value, btype size){for (btype j=0; jclass pavadinimas { }template class Stack { private: Type st[10]; int top; public: Stack() {top = -1;} void push (Type var) { st[++top] = var; } Type pop () { return st [top–]; } };

void main(){Stack s1;s1.push(11.1F);cout< s2;s2.push(123L);cout<class Stack {public:Stack (int max) : stack(new Type[max]), top(-1), maxSize(max) { }~Stack (void) {delete [ ] stack;}void Push (Type &val);void Pop (void) {if (top >= 0) –top;}Type& Top (void) {return stack[top];}friend ostream& operator << (ostream&, Stack&);private:Type *stack;// stack arrayint top; // index of top stack entryconst int maxSize;// max size of stack};

Jei klasės funkcija apibrėžiama už klasės ribų naudojama sekanti sintaksė

template void Stack::Push (Type &val){if (top+1 < maxSize)stack[++top] = val;}

template ostream& operator << (ostream& os, Stack& s){for (register i = 0; i <= s.top; ++i)os << s.stack[i] << ” “;return os;}Šablonai, standartinė šablonų biblioteka (STL) (11paskaita)Klasių šablonai#include using namespace std;template class Stack { private: Type st [10]; int top; public: Stack() { top = -1; }// Konstruktorius void push (Type var) { st [ ++top ] = var; } Type pop () { return st [top — ]; } }; void main() { Stack s1; // s1 – klasės Stack objektas s1.push(11.1F); s1.push(22.2F); cout< s2; s2.push(123L); cout< keičiamas konkrečiu duomenų tipu.

Stack s1(10);// stack of integersStack s2(10);// stack of doublesStack s3(10);// stack of floats

Nontype ParametraiKlasių šablonai gali turėti ne vien tik neapibrėžto duomenų tipo kintamuosius. Ten gali būti ir kintamieji, kurių tipas iš karto apibrėžiamas.

template class Stack {public: Stack (void) : stack(new Type[maxSize]), top(-1) { }~Stack (void) { delete [ ] stack; }void Push (Type &val);void Pop (void) { if (top >= 0) –top; }Type &Top (void){ return stack [top]; }private:Type *stack;// stack arrayint top; // index of top stack entry };

Stack s1;// okStack s2;// illegal! 10u doesn’t match intStack s3;// okint n = 10;Stack s4;// illegal! n is a run-time valueKlasių šablonų nariai (Class Template Members)Klasių šablonų nariai gali būti konstantos, reference, static nariai t.y. tokie pat kintamieji, kaip ir įprastinėse klasėse. Jei šablone yra statiniai kintamieji, kiekviena klasė, sukurta pagal tokį šabloną turi savo statinius kintamuosius.template class Stack {public: //…Type& Top(void);private://…static Type dummy;// dummy entry};template Type& Stack::Top (void){ return top >= 0 ? Stack [top] : dummy; }

template Type Stack::dummy = 0;

Klasių šablonai ir draugiškos klasės(funkcijos)Klasių šablonuose gali būti draugiškos klasės ir funkcijos. Sakykime, kad turime draugišką funkcijos šabloną Foo ir draugišką klasės šabloną Stack.

template class Sample { // one-to-many friendshipfriend Foo;friend Stack;};template class Sample { // one-to-one friendshipfriend Foo;friend Stack;};template class Sample { // many-to-many friendship template friend Foo; template friend class Stack;};

Klasių šablonai ir paveldimumasKlasių šablonai gali būti tiek bazinėmis klasėmis tiek ir išvestinėmis klasėmis.

template class SmartList : public List;// bazinė klasė šablonas

class X;template class Y : X;// išvestinė klasė šablonas

template class Set : public List {public: virtual void Insert (const Type &val) { if (!Member(val)) List::Insert(val); }};

Šablonų apibendrinimasn Šablonai – tai C++ savybė, leidžianti kurti parametrizuoto tipo funkcijas ir klases, kurių pagalba galima kurti klases ar funkcijas keičiančias savo elgseną priklausomai nuo parametrų. Šablonai – tai galimybė pakartotinai naudoti jau sukurtus programinius kodus.n Šablonus apibrėžia parametrizuoti kintamieji.n Klasių šablonai gali turėti draugiškas klases ir funkcijas bei klasių ir funkcijų šablonus.n Šablonai gali turėti ir statinius kintamuosius. Tuo atveju kiekviena šablono konkretizacija kuria atskirus savo statinių duomenų rinkinius.

Standartinė šablonų biblioteka (STL)n STL – tai konteinerinių klasių (vektoriai, sąrašai, eilės, stekai) ir bendro pobūdžio algoritmų (rūšiavimo, paieškos, kopijavimo) biblioteka.n STL įtraukta į C++ standartą ir platinama nemokamai.n STL tikslas – neišradinėti dviračio ir naudotis jau sukurtais ir patikimai veikiančiais klasių bei funkcijų šablonais.n STL sudaro:q Konteineriai – tai būdas, kaip duomenys yra saugomi atmintyje. Duomenys gali būti tipiniai (int, float…) arba objektai;

n Nuoseklūs konteineiriain Asociatyviniai konteineriaiq Algoritmai – tai procedūros (funkcijos), kurios taikomos konteinerio duomenų apdorojimui. Šios funkcijos nepriklauso klasėms;q Iteratoriai – tai apibendrintos rodyklės, jungiančios algoritmus ir konteinerių elementus. Didinant ar mažinant iteratoriaus reikšmę, pasiekiamas vis kitas konteinerio elementas.KonteineriaiKonteineriai – tai alternatyva masyvams. Konteinerių privalumas – didesnis duomenų apdorojimo greitis. Masyvais C++ laikomas duomenų saugojimo būdas, kai jo elementų skaičius apibrėžiamas iš anksto. Pvz. A[10]STL apibrėžia 7 konteinerių tipus, kurie skirstomi į dvi kategorijas: nuoseklūs ir asociatyviniai.Nuoseklūs konteineriai:• vektoriai (vector)• sąrašai (list)• dekai (deque)• stekai (stack)• eilės (queue)• prioritetinės eilės (priority_queue)

Nuoseklūs konteineriai (vektoriai)Nuosekliuose konteineriuose saugomi duomenys gali būti įsivaizuojami kaip pvz. linija namų gatvėje. Visi elementai turi savo poziciją bei kaimynus.Vektoriai – tai konteinerinė klasė, kurios elementai pasiekiami pagal indeksą. Vektoriai panašūs į vienmačius masyvus, tačiau jie yra dinaminiai bei užtikrina indeksų kontrolę.Vektorių klasė apibrėžta antraštės faile vector.h ir naudoja std vardų erdvę.#include #include using namespace std;void main(){ vector v;// sudaromas nulinio ilgio vektorius for (int i = 0; i<5; i++) v.push_back(i); // papildomas vektorius elementu, vektoriaus gale cout<<“Vektoriaus dydis”< v1 (arr, arr+4) ;// sudaromas vektorius while ( !v1.empty () ) { cout<< v1.back() <#include using namespace std;void main(){ list ilist; ilist.push_back(30); // elementai talpinami sąrašo gale ilist.push_back(40); ilist.push_front(20);// elementai talpinami sąrašo priekyje ilist.push_front(10); ilist.push_front (10); ilist.unique()// pašalina dublikuotus elementus ilist.reverse()// sukeičia eiliškumą t.y. 40, 30, 20, 10 cout<<“Saraso dydis”< deq; deq.push_back(30);// elementai talpinami deko gale deq.push_back(40); deq.push_front(20); deq.push_front(10); deq[2] = 33;// trečias deko elementas 33 for (int i=0; i < deq.size(); i++) { cout<< deq[ ] < > aStack; stack stackOne;// sukuriamas stekas iš sąrašo konteineriostack< Customer, list > custom_stack

EilėsEilės – taip pat viena iš populiariausių duomenų struktūrų. Duomenys organizuojami pagal principą FIFO (first in, first out), tai reiškia, kad nauji elementai pridedami iš vieno galo (uodegos), o šalinami iš kito galo (pradžios). Kaip ir stekai, eilės – tai bazinių konteinerių modifikatoriai. Eilės bazinis konteineris pagal nulylėjimą – dekas.STL apibrėžta šabloninė klasė queue. Jos pajungimui reikalingas antraštės failas queue.h

// sukuriama eilė iš deko konteinerioqueue queueTwo;// sukuriama eilė iš sąrašo konteinerioqueue > queueOne;queue > queueThree;

Pavyzdys#include #include #include #include #include using namespace std;int main (){queue q; // sudaroma eilė q.push(1); q.push(2); // pildoma elementais cout<< q.front() << endl; q.pop(); // šalinamas pirmas elementas cout<< q.front() << endl; q.pop(); return 0; }

IteratoriaiIteratoriai – tai rodyklių (pointer) vaidmenį atliekantys objektai, kurių pagalba galima pasiekti tam tikrą konteinerio elementą. Dažnai jie naudojami tam, kad nuosekliai (iteratyviai) prisirišti prie vis kito elemento, tai reiškia, kad iteratorių paskirtis surišti konteinerius ir algoritmus. STL iteratoriams sukurti naudojama klasė iterator.Naudojami trijų pagrindinių klasių iteratoriai:§ Judantys į priekį (forward)§ Judantys abiejomis kryptimis (bidirectional)§ Atsitiktiniai (random)Specializuoti iteratoriai darbui su I/O:§ Įvedimo (rodo į įvedimo įrenginį t.y. cin arba failas)§ Išvedimo (rodo į išvedimo įrenginį t.y. cout arba failas)Konteinerio elemento reikšmė gaunama naudojant * simbolį, pvz. value =*iter; Vector List Deque Set Multiset Map MultimapRandom X X Bidirectional X X X X X X XForward X X X X X X XInput X X X X X X XOutput X X X X X X XAlgoritmai taip pat reikalauja tam tikro iteratoriaus tipo, todėl turi būti išlaikytas iteratoriaus suderinamumas iš vienos pusės su algoritmu iš kitos pusės su konteineriu. Aukštesnio lygio iteratorius tinka algoritmui, reikalaujančiam žemesnio lygio iteratoriaus.list iList;list ::iterator iter;#include #include #include void main(){int arr[ ] = {2, 3, 4, 5}; list theList; for (int k=0; k<4; k++) theList.push_back ( arr[k] ); // užpildomas sąrašas elementaislist::iterator iter;for (iter = theList.begin(); iter != theList.end(); iter++)cout<< *iter << ‘ ‘; }

AlgoritmaiSLT saugoma apie 60 universalių algoritmų, kurie atlieka rutinines operacijas su duomenimis. Jie apibrėžti antraštės faile ir naudoja standartinę vardų erdvę std.Pavyzdys:#include #include using namespace std;int arr[ ] = {11, 22, 33, 44, 55, 66,77 };void main(){int *ptr; ptr = find( arr, arr+8; 33); // rasti pirma 33 cout<<“Pirmasis 33” << (ptr- arr);}

Asociatyviniai konteineriaiAsociatyviniuose konteineiriuose elementai siejami su raktais, kurie atlieka indekso funkcijas. Raktais dažniausiai būna skaičiai arba eilutės. STL apibrėžia dvi pagrindines asociatyvinių konteinerių grupes: § set (aibė)§ map (žemėlapis)Aibėse saugomi unikalūs raktai, žemėlapiuose – raktų ir reikšmių poros. Aibėse ir žemėlapiuose raktai unikalūs, tačiau multiaibėse bei multižemėlapiuose raktai gali kartotis.

Norint naudoti asociatyvinius konteinerius, reikia prisijungti antraštės failus map.h arba set.h

Aibės Aibės dažnai naudojamos vartotojo sukurtų objektų saugojimui. Pvz. darbuotojų duomenų bazė. Tačiau aibės gali saugoti ir paprastesnius elementus – eilutes.#include #include #include

void main(){ string names [ ] = {“Jonas”, Petras”, “Ona”, “Antanas”}; // string objektų masyvas set > nameSet(names, names+4); // aibė į masyvą set >::iterator iter; // iteratorius nameSet.insert(“Jurgis”); nameSet.insert(“Mikas”); cout<<“Size”< #include #include

void main(){ string names [ ] = {“Jonas”, Petras”, “Ona”, “Antanas”}; // string objektų masyvas set > nameSet(names, names+4); // aibė į masyvą set >::iterator iter;// iteratorius

nameSet.insert(“Jurgis”); // įterpiamas naujas vardas nameSet.insert(“Mikas”); nameSet.erase(“Mikas”); // šalinamas elementas cout<<“Size”<> searchName;iter = nameSet.find(searchName);if ( iter == nameSet.end() ) cout << “ Vardas “<< searchName << “nerastas” << endl;else cout << “Vardas “<<*iter << “rastas…”< #include #include

void main(){ string name; int pop; string states[ ] = {“Montana”, “Arizona”, “Nevada”, “Colorado”, “Florida”}; int pops[ ] = {470, 280, 787, 985, 562}; map > mapStates; //map map > :: iterator iter; //iterator // string – eilute(raktas), int – reikšmė, less – išrūšiavimas mažėjimo tvarka

for (int j = 0; j<6; j++){ name = states[ j ]; pop = pops[ j ]; mapstates [name] = pop; } cout << “Įveskite valstiją: “; cin >> name; cout << “Gyventojų skaičius “<ybool = less(T, T) x=ybool = less_equal(T, T) x<=yPavyzdys#include #include #include // del funkcijos accumulate()class airtime{private: int hours; int minutes; public: airtime(): hours (0), minutes (0) { } airtime (int h, int min): hours (h), minutes (min) { } void display ( ) const { cout << hours << “ : “ <> hours >> dummy>>minutes; }airtime operator + (const airtime right) const// perktrautas operatorius{ int tmph = hours + right.hours; int tmpmin = minutes + right.minutes if (tmpmin >= 60) {tmph ++; tmpmin -= 60; } return airtime(tmph, tmpmin); }

bool operator = = (const airtime& at2) const{return (hours = = at2.hours)&&(minutes = = at2.minutes) }};void main (){char answer; airtime temp, sum; list airlist; // sąrašas padarytas iš airtime do { temp.get (); airlist.push_back (temp); // įterpiamas objektas temp sąrašo gale cout >> “ Dar įvedinėsite (y/n)? ” ; cin >> answer; } while (answer != ‘n’);

sum = accumulate (airlist.begin(), airlist.end(), airtime(0,0), plus() );sum.display();cout << endl; }

Funkcija accumulate() sudeda sąrašo elementus pradedant nuo pirmo ir baigiant paskutiniuoju. Sudėčiai naudojama funkcija objektas plus, sumavimas atliekamas į airtime(0,0) objektą.

Objektiškai orientuotas projektavimasOOD (object oriented design) – tai programuojamos problemos modelio sukūrimas, naudojant klases bei jų savybes.OOD sudaro trys fazes: 1. CRC card (CRC kortelė) 2. Use cases (Panaudojimo stadija) 3. Class diagrams (Klasių diagramos)CRC cards – tai problemos analizė netechniniu požiūriu. Tai paprastai atlieka business domain experts (BDEs), kurie žino kaip programa turi veikti. Kiekviena kortelė atitinka tam tikrą objektą, kuris bus naudojamas programoje.Use case – tai programos specifinių operacijų aprašymas. Šitoje stadijoje gali išaiskėti, kad CRC cards turi būti modifikuotos ar sukurtos naujos papildomos.Class diagrams – tai stadija, kai nustatomas ryšys tarp planuojamų sukurti klasių bei įrašoma informacija į CRC cards. Šioje stadijoje naudojama UML (Universal Modeling Language).