You are on page 1of 9

Mihai TOGAN

Cap. 1 – Elemente introductive

Obiective:
 Funcții cu parametrii impliciți
 Funcții cu acelaşi nume
 Tipul de date referinţă (&)
 Alocatorul new/delete
 Streamuri de intrare/ieșire (cin /cout)
 Concepte OOP (introductiv)

1
Mihai TOGAN
Funcții cu parametrii impliciţi
#include <iostream>

float get_point_distance (int x = 0, int y = 0, int z = 0)


{
return (float) sqrt (x*x + y*y + z*z);
}

void main()
{

printf ("%f\n", get_point_distance(1, 2, 3)); /* distance to (1,2,3) */


printf ("%f\n", get_point_distance(1, 2)); /* distance to (1,2,0) */
printf ("%f\n", get_point_distance(1)); /* distance to (1,0,0) */
printf ("%f\n", get_point_distance()); /* distance to (0,0,0) */
}

Alte variante OK:


float get_point_distance (int x, int y, int z)
float get_point_distance (int x, int y, int z = 1)
float get_point_distance (int x, int y = 2, int z = 1)

Variante greşite:
float get_point_distance (int x, int y = 0, int z)
float get_point_distance (int x = 1, int y, int z)
float get_point_distance (int x = 1, int y = 0, int z)

Observaţii:
 Parametrii unei funcţii pot avea valori implicite.
 Parametrii cu valori implicite trebuie sa fie la finalul listei de parametrii.
 Atenţie: uneori, mecanismul este ȋnsă nerecomandat (!!). Poate conduce ușor la erori
de scriere a programelor (cu erori de execuţie şi buguri greu de detectat).
 Atenție de asemenea la cazurile de ambiguitate!

2
Mihai TOGAN
Funcții cu acelaşi nume (function overloading)

Varianta 1: generăm câte o funcţie diferită pentru fiecare scenariu de aplicare.


#include <stdio.h>

int add_int(int x, int y)


{
return x + y;
}

float add_float(float x, float y)


{
return x + y;
}

struct t_Complex
{
float re;
float im;
};

struct t_Complex add_complex(struct t_Complex x, struct t_ Complex y)


{
struct t_Complex c = {x.re + y.re, x.im + y.im};
return c;
}

void main()
{
int i = add_int (1, 2); /* suma a 2 nr intregi */
float f = add_float ((float) 1, 2.0); /* suma a 2 nr reale */

t_Complex x = {1.0, 2.0}, y = {3.0, 4.0};


t_Complex z = add_complex (x, y); /* suma a 2 nr complexe */

printf ("%d\n", i);


printf ("%f\n", f);
printf ("z = (%d, %d)\n", z.re, z.im);
}

Varianta 2 (function overloading): Implementăm 3 funcţii având acelaşi nume şi


comportament diferit.
#include <stdio.h>

int add(int x, int y)


{
return x + y;
}

3
Mihai TOGAN

float add(float x, float y)


{
return x + y;
}

struct t_Complex
{
float re;
float im;
};

struct t_Complex add(struct t_Complex x, struct t_Complex y)


{
struct t_Complex c = {x.re + y.re, x.im + y.im};
return c;
}

void main()
{
printf ("%d\n", add (1, 2)); /* suma a 2 nr intregi */
printf ("%f\n", add ((float) 1, 2.0)); /* suma a 2 nr reale */

t_Complex x = {1, 2}, y = {3, 4};


t_Complex z = add(x, y); /* suma a 2 nr compexe */
printf ("z = (%d, %d)\n", z.re, z.im);
}

 Compilatorul generează cod obiect pentru apelul funcției corecte folosind pentru asta
tipul parametrilor de apel.
 Funcţii cu acelasi nume (function overloading)  variantă de polimorfism.
 Este necesar sa difere semnătura funcţiei (în cazul nostru lista de parametrii).
 Atenţie la cazurile de ambiguitate!
 Q: care este avantajul ?

4
Mihai TOGAN
Tipul de date referinţă (&)

Consideraţii iniţiale:
 Referinţa este un alias pentru o variabilă.
 Dacă variabila reprezintă o anumită zonă de memorie, și referinţa va reprezenta
aceeaşi zonă de memorie.
 Întotdeauna, o referințǎ se declarǎ cǎtre ceva care existǎ deja declarat (alocat).
 Nu se alocǎ memorie suplimentarǎ.
 Referinţele se declară cu (&).

Exemplul 1:

#include <iostream>
void main()
{
int x = 5;
int& y = x;
printf ("%d\n", y); // 5
y++;
printf ("%d\n", x); // 6

const int a = 10;


const int& b = a; // referinta constanta (catre un intreg constant)
// b++; // eroare de compilare !!
}

Exemplul 2:

 Referinţa este des folositǎ la transmiterea parametrilor în funcţii (transmiterea prin


referinţă):

#include <iostream>
void schimba (int &x, int &y)
{
int z = x;
x = y;
y = z;
}

void main()
{
int a = 10, b = 20;
printf ("%d, %d\n", a, b); // 10, 20
schimba (a, b);
printf ("%d, %d\n", a, b); // 20, 10
}

Notă: necesită explicaţie suplimentară privind comparaţia dintre mecanismele C++ și


mecanismele alternative din C.

5
Mihai TOGAN

Exemplul 3:

 Referinţa poate fi utilizată pentru întoarcerea valorilor din funcții:

#include <iostream>
struct t_Point
{
int a;
int b;
};

struct t_Point& suma (const struct t_Point& x, const struct t_Point& y)


{
struct t_Point *pz = (struct t_Point *) malloc (sizeof(struct t_Point));
pz->a = x.a + y.a;
pz->b = x.b + y.b;

return *pz;
}

void print_point (const struct t_Point& P)


{
printf ("(%d, %d)", P.a, P.b);
}

void main()
{
t_Point x = {1, 2}, y = {3, 4};
t_Point z = suma (x, y); /* suma a 2 puncte */

print_point (z); // (4, 6)


}

Q: ce problemă există în programul de mai sus?

6
Mihai TOGAN
Alocatorul de memorie din C++ (new/delete)
 Varianta C++ pentru alocarea dinamică de memorie (echivalentul C++ pentru alloc/free).

Varianta C (malloc/free)
#include <stdio.h>
#include <stdlib.h>
void main ()
{
int *p1 = (int *) malloc (sizeof (int)); // alocare 1 intreg
*p1 = 12;
// ...
printf ("%d", *p1);

int n = 20;
int *p2 = (int *) malloc (n * sizeof (int) ); // alocare n=20 intregi
// ...
unsigned char *p3 = (unsigned char*) malloc (n); //alocare n = 20 bytes
// ...
free (p1); // eliberare memorie (1 intreg)
free (p2); // eliberare memorie (20 intregi)
free (p3); // eliberare memorie (20 octeti)

Varianta C++ (new/delete):


#include <stdio.h>
void main ()
{
int *p1 = new int; // alocare 1 intreg
*p1 = 12;
// ...
printf ("%d", *p1);

int n = 20;
int *p2 = new int[n]; // alocare n=20 intregi
// ...
unsigned char *p3 = new unsigned char[n]; // alocare n = 20 intregi
// ...
delete p1; // eliberare memorie (1 intreg)
delete[] p2; // eliberare memorie (20 intregi)
delete[] p3; // eliberare memorie (20 bytes)
}

 Operatorii new/delete folosesc alocatorul din C++.


 Se pot folosi ȋn continuare şi funcţiile malloc/free. Folosesc alocatorul „moştenit” din C.
 Alocatorul C++ este mai performant (viteză de execuţie) faţă de cel din C.
 Operatorii new/delete sunt integraţi cu alte mecanisme C++ (apelul automat al
constructorilor şi destructorilor).
 Nu mai necesită operator suplimentar de cast (operatorul new se „adaptează”).
 Atenţie: Nu sunt permise apelurile încrucişate: new/free sau malloc/delete (crash !!).
Explicaţie suplimentară privind codul din alocatoare.
 Discuţie delete vs. delete[ ].
7
Mihai TOGAN
Streamurile standard de intrare/ieșire (cin, cout)
 Citire de la tastatură, streamul standard de intrare cin
 Afişare pe consola standard, streamul standard de ieșire cout
 Se folosesc operatorii de redirectare >> , <<
Exemple
#include <iostream>
using namespace std;

int main ()
{
char str[] = "Hello C++";
cout << "Value of str is : " << str << endl;
}

Programul afişează: Value of str is : Hello C++


#include <iostream>
using namespace std;

int main ()
{
int n = 10;
cout << "Value of n is : " << n << endl;
}

Programul afişează: Value of n is : 10


#include <iostream>
using namespace std;

int main ()
{
int i;
cout << "Please enter an integer value: ";
cin >> i;
cout << "The value you entered is " << i;
cout << " and its double is " << i*2 << ".\n";
return 0;
}

#include <iostream>
using namespace std;

int main ()
{
char name[50];
cout << "Please enter your name: ";
cin >> name;
cout << "Your name is: " << name << endl;
}

 Discuţie privind cerr, clog, namespace-ul std.


 Necesită #include <iostream>
 Streamurile se „adaptează” la tipul datelor
 Pot fi realizate diverse formatări (@temă de casă)
8
Mihai TOGAN
Concepte OOP (discuţie introductivă)

Ideea principală OOP: abstractizarea (în scop de generalizare) !

Exemplu folosit în discuţie: ne propunem sa modelam (implementam) un pix pentru scris.

 Abordarea POO este aceea de a modela un obiect de scris (abstract, general).


 Entitatea are o serie de proprietăţi: formă, dimensiuni, culoare de scris, culoare carcasă,
etc.
 Entitatea are un comportament (functionalităţi): scrie, reîncarcă, etc.
 Pe baza entităţii generale de scris putem apoi particulariza (concretiza) pixul de scris.
 Pe baza entitatii generale ne putem extinde usor la alte tipuri de obiecte de scris: stilou,
pen electronic, etc.

Conceptele generale OOP sunt:

A) Încapsularea
 Pentru orice problemă identificăm entităţile implicate.
 Entităţile interacţionează între ele, sau sunt grupate pentru a forma alte entităţi mai mari.
 Fiecare entitate are nişte atribute/proprietăţi (o structură de date).
 Fiecare entitate are un comportament (o funcţionalitate asigurată prin funcţii).
 Ideea încapsulării: grupăm structura de date şi funcţionalităţile la un loc în cadrul unui
container (clasa).
 Partea publică: o parte din componentele unei clase sunt interfeţe pentru interacţiunea cu
alte entităţi externe.
 partea privată: celelalte componente sunt de uz strict intern, la nivelul clasei; nu vor
interacţiona în mod direct cu alte entităţi.

B) Moştenirea
 Moştenirea  reutilizarea codului.

 Pe baza unor componenete (clase) deja implementate putem deriva apoi alte componente
care în primul rând păstrează structura de date şi comportamentul iniţial, şi la care putem
adăuga sau modifica.

C) Polimorfismul
 Comportament polimorfic  comportament „diferit” în situaţii diferite.

 Mecanismele tehnice existente în limbajul C++ pentru polimorfism sunt:


 funcţii cu acelaşi nume (function overloading)
 moştenire şi metode virtuale (virtual functions)
 funcţii şi clase template (templates)

You might also like