Transcript
Page 1: 0.0 particularitatile programarii с++

PARTICULARITĂȚILE ELABORĂRII APLICAȚIILOR C++

Croitor Mihail

Page 2: 0.0 particularitatile programarii с++

Cuprins

Pointer la funcție Moștenire Funcții virtuale

Polimorfism în baza funcțiilor virtuale Clase abstracte

Redefinire operatorilor Obiecte funcționale Șabloane

Polimorfism static Specializare șabloanelor

Unele particularități ale standardului C++11

Page 3: 0.0 particularitatile programarii с++

Pointer la funcție

Pointer la funcție este un pointer, care conține adresa punctului de întrare în această funcție.

Declararea variabilei-pointer la funcție:void (*pfunc)(double*, const size_t);

Declararea tipului pointer la funcție:typedef void (*pfunc_t)(double*, const size_t);

Page 4: 0.0 particularitatile programarii с++

Pointer la funcție: exemplu

#include <stdio.h>typedef void (*event_t)(void*, void*);

struct Button{    size_t x, y, width, height;    char text[255];    event_t OnClick;};

void ButtonPressed(void* /*sender*/, void* /*arg*/){    puts("button pressed!");}

int main(){    Button btn = {5, 5, 75, 30, "Press Me!", ButtonPressed};    btn.OnClick();    return 0;}

Page 5: 0.0 particularitatile programarii с++

Moștenire

Moștenirea este un mecanism, care permite descrierea clasei noi (clasa copil, clasa derivată) în baza unei clase existente (clasa de bază, clasa părinte) cu păstrarea funcționalității clasei de bază.

Moștenirea permite manipularea cu obiecte de clasa derivata ca cu obiecte clasei de bază.

Pointer la obiectul clasei de bază poate referi la obiectul clasei derivate. Afirmație inversă este greșită.

class Base {int value;

public:Base(): value(0){}int getValue() { return value; }

};

class Derived: public Base{public:

Derived() : Base() {}void setValue(int data) { value = data; }

};

Exemplu moștenirii:

Page 6: 0.0 particularitatile programarii с++

Moștenire: exemplu

class Entity{protected:

std::string name;Entity* parent;

public:virtual std::string ToString() const = 0;Entity* GetParent() const{ return parent; }

};

class Folder: public Entity{std::list<Entity*> childs;

public:Folder(std::string n, Entity* p): name(n), parent(p){}std::string ToString() const { return name; }

};

Page 7: 0.0 particularitatile programarii с++

Funcții virtuale

Funcție virtuală a clasei este o metodă, care poate fi redefinită în clasa copil și în dependența de situație se determină în timpul executării aplicației care realizarea concretă a funcției va fi apelată.

Polimorfismul în baza funcţiilor virtuale se numeste polimorfism dinamic. Această proprietate printre altele permite invocarea unei şi aceleiaşi funcţiei (fără redeclararea/redefinirea) cu parametrii actuali de diferite tipuri.

class Base{public: Base(): value(0){} virtual void show() { std::cout << "Base" << std::endl; }}; class Derived: public Base{public: Derived() : Base() {} virtual void show() { std::cout << «Derived" << std::endl; }};

Exemplu:

Page 8: 0.0 particularitatile programarii с++

Funcții virtuale:exemplu de polimorfism

class Base{public: Base(): value(0){} virtual void show() { std::cout << "Base" << std::endl; }}; class Derived: public Base{public: Derived() : Base() {} virtual void show() { std::cout << "Derived" << std::endl; }}; void print(Base* p) { p->show(); } int main(){ Base* b = new Base(); Derived* d = new Derived();  print(b); print(d); return 0;}

Page 9: 0.0 particularitatile programarii с++

Funcții virtuale:clase abstracte

O funcție virtuala poate fi declarata in clasa fără definirea corpului ei. In acest caz funcția se egalează cu zero si se numește funcția virtuală pură sau funcția abstractă. Daca o clasa conține cel puțin o funcție virtuala pura, atunci aceasta clasa se numește clasa abstracta.Orice funcție abstractă se redefinește în clasa-copil.Clasele abstracte se utilizează în cazuri când programator are nevoie de o mulțime de clase cu comportament comun.

struct Shape{virtual void Draw() = 0;virtual void Hide() = 0;

};struct Point: Shape{

virtual void Draw(){ // draw this point

}virtual void Hide(){ // hide this point}

};Clase abstracte sunt asemănătoareinterfețelor din Java și C#

Page 10: 0.0 particularitatile programarii с++

Redefinirea operatorilor

pentru comoditate, este utila supraîncărcarea (redefinirea) unui operator standard pentru o clasa. Programul in acest caz devine mai compact si mai clar. Forma comuna pentru supraincarcare este urmatoarea:<return_type> operator <operator_sign> (<operator_parametres>);

сlass int_pair{    int first, second;public:    int_pair(int f = 0, int s = 0): first(f), second(s) {}    bool operator == (const int_pair& p) const {        return (first == p.first) && (second == p.second);    }};

bool operator != (const int_pair& p1, const int_pair& p2){    return !(p1 == p2);}

pentru a determina locul de declarare a operatorului - in cadrul clasei, sau in afara ei - întrebați-va, daca acest operator schimba parametrii de intrare. Daca da, atunci se recomanda declararea acestui operator in clasa, dacă nu, atunci mai bine declarați-l in afara clasei.

Page 11: 0.0 particularitatile programarii с++

Obiecte funcționale

In declarația clasei poate fi supraîncărcat operatorul (). Daca acest operator este supraîncărcat, atunci obiectele acestei clase obțin unele proprietăți ale funcțiilor (ele pot fi utilizate in același mod ca si funcții). Aceste obiecte se numesc obiecte funcționale sau functori. Utilizarea functorilor este comoda atunci când funcția trebuie sa aibă "memorie", sau ca o alternativa pointerilor la funcție.

// functor care socoate numărul de apeluriclass _swap{    static size_t counter = 0;    static void increment() { ++counter; }public:    _swap(){}    void operator ()(int& a, int& b){        int tmp = a;        a = b;        b = tmp;        inc();    }    int getNrCalls() {return count; }};_swap swap;int a = 3, b = 5;swap(a, b);

Page 12: 0.0 particularitatile programarii с++

Șabloane

Șablonul clasei reprezintă un mecanism de generare a familiei de clase cu comportament comun

Șablonul funcției reprezintă un mecanism de generare a familiei de funcții cu comportament comun

template<class TYPE>void swap(TYPE& p1, TYPE& p2){    TYPE tmp = p1;    p1 = p2;    p2 = tmp;}

Noțiunea șablonul funcției deseori se asociază cu noțiunea de algoritm.

Page 13: 0.0 particularitatile programarii с++

Șabloane: polimorfism static

int main(){    int i1 = 3, i2 = 5;    float f1 = 1.2, f2 = 2.3;    double d1 = 1.003, d2 = 10;    swap(i1, i2);    swap(f1, f2);    swap(d1, d2);    return 0;}

În exemplu dat, una si aceeași denumirea funcției este utilizata cu tipuri de date diferite. Aceasta proprietate, realizată cu ajutorul șabloanelor, se numește polimorfism static, deoarece determinarea comportamentului funcției are loc la etapa de compilare a programului.

Page 14: 0.0 particularitatile programarii с++

Șabloane:specializarea șabloanelor

Pentru un tip de date concret poate fi definită o versiune specială a șablonului.

template<>void swap(int* a, int* b){

int tmp = *a; *a = *b;

*b = tmp;}

Dacă un șablon (și/sau specializarea lui) nu se utilizează în codul sursă atunci la etapa de compilare el nu se include în codul binar!

Page 15: 0.0 particularitatile programarii с++

С++11: tipuri automate

Cuvântul cheie auto spune compilatorului să determine tipul variabilei in mod automat, după valoare

auto val = 5;

Page 16: 0.0 particularitatile programarii с++

С++11: inițializatori

A apărut posibilitatea inițializării claselor containeri cu ajutorul listelor de inițializare.

class Array10{    int _val[10];public:    Array10(std::initializer_list<int> list);};

Array10 a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};

Page 17: 0.0 particularitatile programarii с++

С++11: lambda-funcții

Expresii lambda permit programatorilor să accelereze scrierea codului. Sub expresii lambda înțeleg un mod special de definirea functorilor.

[](int x, int y) { return x + y; } 

// то же, что и [](int x, int y) -> int{ int result = x + y; return result; }

struct sum{    int opertator()(int x, int y){ return x+y;}

};

Page 18: 0.0 particularitatile programarii с++

C++11: pointer nul

Utilizarea valorii 0 ca pointer nul în unele cazuri aducea la cod periculos. Se recomandă utilizarea cuvântului cheie nullptr.

void test(int);void test(char*);int main(){ test(0); // ??? test(nullptr); // !!! return true;}

Page 19: 0.0 particularitatile programarii с++

С++11: buclă «pentru fiecare»

int a[5] = {1, 2, 3, 4, 5};

for(auto& el: a){++el;}

for(auto el: a){std::cout << el << " ";}

Standard nou С++ propune o formă nouă de bucla for: for( type element: collection){}

Page 20: 0.0 particularitatile programarii с++

Mulțumesc de atenție!