Documente Academic
Documente Profesional
Documente Cultură
Curs
Programarea Orientată Obiect
SPATARU VIRGIL
++
C POO
26.11.18 0
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
1. Redactarea programelor C
1.1. Generalităţi
Mediul Borland C a fost extins la Visual C şi C++ Builder, adaptate programării
orientate obiect şi interfeţei grafice Windows 95. Limbajul C a fost extins la C++ permiţând
aplicarea conceptelor programării prin abstractizarea datelor şi programării orientate spre
obiecte.
Fişierele sursă pot avea extensia C, CP, sau CPP.
1.2. Structura unui program
Un program C este conţine o funcţie principală (main) şi eventual alte funcţii
secundare, apelate de către funcţia principală, situate la acelaşi nivel (fară imbricare).
Structura unui program este următoarea:
Directive de procesare,
Declaraţii de date globale,
Declaraţii de funcţii, sau doar [ Antete de funcţii (prototipuri) ]
Funcţia principală;
[ Descrierea funcţiilor (implementări) ]
Se observă că descrierea funcţiilor se poate face fie în întregime înaintea funcţiei
main fie doar prototipul înainte, iar corpul după aceasta.
Comentariile se scriu între caracterele /* şi */ ( ... /* comentariu */ ... ), sau la
nivelul unui rând după caracterele // ( ... // comentariu ).
Înainte de compilare, un program este precompilat, de către un preprocesor, care
permite includerea unor fişier sursă, definirea şi apelul unror macrouri, precum şi o
compilare condiţionată.
Includerea unui fişier sursă (*.h sau *.c) se realizează prin directiva include astfel:
# include “specificator_fişier” // pentru fişiere utilizator
sau
# include <specificator_fişier> // pentru fişiere standard
Exemplu:
#include <stdio.h>; // Standard Input Output Header
#include <iostream.h>; // Console Input, Console Output
26.11.18 1
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Constantele simbolice se definesc cu ajutorul directivei define astfel:
#define Nume_constantă Şir_caractere
Exemplu:
#define Pi 3.141592 // Înlocuieşte Pi cu 3.141592
O constantă simbolică poate fi redefinită sau anulată (#undef Nume_constantă).
1.3. Funcţii
O funcţie este formată dintr-un antet şi un bloc (corp). Ea poate fi apelată dacă a
fost definită în întregime sau doar antetul său.
Antetul unei funcţii are următorul format:
Tip Nume (Listă_parametri_formali)
unde:
Tip este tipul valorilor funcţiei (codomeniul);
Nume este un identificator (literă urmată eventual de alte litere sau cifre);
Listă_parametri_formali conţine parametrii formali separaţi prin ‘,’.
26.11.18 2
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
1.4. Elementele limbajului
Alfabetul limbajului C este format din litere mari şi mici, cifre şi caractere speciale
(\n=CrLf, \t=Tab).
Identificatorii sunt formaţi din literă_ urmată eventual de litere_ sau cifre
(caracterul ‘_’ poate fi utilizat pe post de literă).
Există cuvinte cheie care pot fi utilizate doar în contextul definit (de exemplu case,
float, int, long, return, short, static, structure, switch, union, unsigned, void).
Tipurile predefinite sunt următoarele:
int (Z [-215,215-1]),
short (Z [-215,215-1]),
long (Z [-231,231-1]),
unsigned (N [0,216-1]),
float (Q* [-3.410-38, 3.41038]),
double (Q* [-1.710-308, 1.710308]),
char (cod ASCII).
Constantele numerice pot fi zecimale (123, 123Long, 111long), octale (077), hexa
(0xabba, 0Xfac), sau flotante (2.71828, 6.023e23, 6.023E23).
Constantele de tip caracter pot fi afişabile ('A', '0', '"') sau funcţionale
('\b'=Backspace, '\r'=Return, '\n'=Newline, '\''=Apostrof, '\\'=Backslash, '\v'=Verticaltab,
'\f'=Salt de pagină, '\0'=Null.
Constantele de tip şir de caractere se scriu între ghilimele ("Mesaj").
26.11.18 3
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
2. Variabile
Variabilele pot fi statice sau dinamice, locale sau globale.
2.1. Variabile globale
Declararea unei variabile globale se face la începutul unui fişier sursă (în afara
tuturor funcţiilor) şi poate fi referită până la sfârşitul programului (în orice funcţie).
Utilizarea lor în alte fişiere sursă se poate face doar dacă acestea sunt declarate ca variabile
externe:
extern declaraţie_variabilă
Exemplu:
VExterne.Cpp:
#include <stdio.h>;
#include "Fs.h";
float Pi=3.14; // variabilă globală
void main (void)
{ float r;
printf(" Dati raza cercului : "); scanf("%f",&r);
printf(" Lungimea cercului = %f \n",LungC(r));
scanf ("\n");
}
Fs.h:
float LungC (float r)
{
extern float Pi; // variabilă externă
return 2*Pi*r;
}
26.11.18 4
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemplu:
VLocale.Cpp:
#include <stdio.h>;
#include "Sursa.h";
void main (void)
{ int n;
printf(" Dati un numar < 256 : "); scanf("%d",&n);
printf(" Valoarea in Hexa este ");
Print_Hexa(n);
// Print_Byte(n/256); Print_Byte(n%256); !?
scanf ("\n");
}
Sursa.h:
static int Cifra_Hexa (int s)
{
static int c;
if (s<10) c=s+'0';
else c=s+'A'-10; // c=s+'0'+7
return c;
}
static void Print_Byte(int b)
{
static int H = b / 16;
static int h = b % 16;
printf("%c%c",Cifra_Hexa(H),Cifra_Hexa(h));
}
void Print_Hexa(int z)
{
static int HH = z / 256; Print_Byte(HH);
static int hh = z % 256; Print_Byte(hh);
}
26.11.18 5
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
2.4. Iniţializarea variabilelor
Exemple:
float f ( int n );
{ int i=1;
int m=n/2;
...
}
26.11.18 6
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
3. Expresii
O expresie este formată din operanzi, operatori şi paranteze pentru prioritate, şi
are o valoare şi un tip. Asocierea operatorilor se face de la stânga la dreapta, cu excepţia
operatorilor unari şi de atribuire, care se asociază de la dreapta la stânga.
Operanzii pot fi: constante, constante simbolice, variabile simple sau structurate
(tablouri, structuri, sau elemente ale acestora), funcţii sau apeluri de funcţii.
3.1. Operatori
( ) [ ]
(unar) + (unar) * (unar) & (unar) ! ~ ++ (tip) sizeof
* / %
+
<< >>
< <= >= >
== !=
&
^
|
&&
||
?: (ternar)
= *= /= %= += = <<= >>= &= ^= |=
,
26.11.18 7
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Operatorii relaţionali sunt următorii:
Deoarece nu există tipul boolean, valoarea fals este reprezentată prin 0, iar
adevărat prin orice valoare diferită de 0.
Exemplu:
// ASCII
#include <stdio.h>;
#include <conio.h>;
int Cifra(int c) // cifra hexa: 01...9AB...F
{
if (c<10) return c | '0';
else return (c-9) | '@';
}
int c;
void main (void)
{ textbackground(BLUE); textcolor(WHITE); clrscr();
do { printf(" Dati un caracter #Esc : "); c=getch();
printf(" ... Hexa = %c%c \n",Cifra(c>>4),Cifra(c&0xF)); }
while (c!=0x1B);
}
26.11.18 8
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemple:
a = ++b; // b=b+1; a=b;
a = b ; // a=b; b=b1;
26.11.18 9
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Conversiile implicite (realizate automat) se fac astfel:
a) charint,
b) floatdouble,
c) (double,*)(double,double)=double,
d) (long,*)(long,long)=long,
e) (unsigned,*)(unsigned,unsigned)=unsigned.
Operatorul virgulă permite gruparea mai multor expresii într-una singură, aceasta
având valoarea ultimei expresii:
26.11.18 10
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
4. Operaţii de intrare/ieşire
Funcţia printf returnează numărul de octeţi afişaţi dacă operaţia a decurs corect,
iar în caz contrar -1 (EOF):
if (EOF = = printf (Control , Listă_Expresii)) ... eroare ... ;
26.11.18 11
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemplu:
short Zi=1; char Luna[]="Ianuarie"; unsigned An=2003;
float Ina=1.8;
printf(" Zi:%d, Luna:%3.3s., An:%u \n",Zi,Luna,An); // Zi:1, Luna:Ian., An:2003
printf(" Inaltime(m):%4.2f \n",Ina); // Inaltime(m):1.80
26.11.18 12
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
4.3. Funcţia PutChar
Această funcţie realizează tipărirea unui caracter al cărui cod ASCII este precizat
printr-o expresie:
putchar (Expresie);
4.4. Funcţia GetChar
Aceasta, returnează codul ASCII al caracterului citit (pentru Ctrl/Z EOF=-1):
getchar ( );
Exemplu:
char c;
do putchar (((c=getchar())>'Z')? c^' ' : c); // Litere mici LITERE MARI
while (c!='.'); // se termină cu .
Litere mici in Litere MARI ! getchar
LITERE MICI IN LITERE MARI ! putchar
Se termina la . (Punct) getchar
SE TERMINA LA . putchar
LLiIt TeErReE mMiIcCiI iInN LLiIt TeErReE MMAARRII..
LITERE MICI IN LITERE MARI. // S-a tastat: Litere mici in Litere MARI.
26.11.18 13
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
5. Instrucţiuni
;
5.2. Instrucţiunea Expresie
Instrucţiunea are formatul general:
Expresie ;
Exemple:
y = (x+1)*(x-1); // Atribuire: v=Expresie;
f(x,y); // Apel de funcţie: f(p1, p2,... , pn);
c++; --c; // Incrementări/Decrementări (Pre/Post fixate)
26.11.18 14
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
5.4. Instrucţiunea If
Structura alternativă cu una sau două ramuri poate fi scrisă astfel:
if (expresie) instructiune1;
[ else instructiune2; ]
Exemplu:
{ P(x,y) I-ul Cadran (Dacă x sau y este negativ se schimbă semnul )
float x, y;
printf(" Dati P(x,y) = "); scanf("%f %f", &x,&y); // Punctul P
if (x>0) if (y<0) y=-y; // C4 else_; (instrucţiunea vidă)
else { x=-x; // C2 sau C3 (x)
if (y<0) y=-y; // C3 (y)
}
printf(" x=%5.2f, y=%5.2f \n", x,y) ;
} // trebuie pus pentru C1 instrucţiunea vidă: else_;
26.11.18 15
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemplu:
// Nr.Zile / lună \\
#include <iostream.h>
#include <conio.h>
void main (void)
{ int l,a;
cout << " Dati anul : "; cin >> a;
cout << " Numar de zile ... " << endl;
for (l=1; l<=12; l++) {
cout << l << " : ";
switch (l) {
case 2 : cout << (a&3 ? 28 : 29); break;
case 4 :
case 6 :
case 9 :
case 11 : cout << 30 ; break;
default : cout << 31 ; // break;
} cout << endl;
}
getche();
}
26.11.18 16
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
5.8. Instrucţiunea For
continue;
Exemplu:
for (... ;... ; expr3) { ...
if (expr) continue;
... }
Exemplu:
26.11.18 17
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
while (expr1) { ...
if (expr2) goto et;
... }
...
et: ... // instrucţiune
O funcţie poate fi utilizată doar dacă a fost definită sau cel puţin a fost declarat
prototipul ei într-una din următoarele moduri:
a) Tip_ funcţie Nume_ funcţie (Lista_parametrilor_formali);
b) Tip_ funcţie Nume_ funcţie (Lista_tipurilor_parametrilor_formali);
c) Tip_ funcţie Nume_ funcţie (Void); // nu sunt parametri formali
d) Tip_ funcţie Nume_ funcţie ( ); // nu se fac verificările de tip
Apelul implicit pentru variabile simple (de bază) este prin valoare, iar pentru
tablouri prin referinţă. Apelul prin referinţă se obţine prin intermediul variabilelor de tip
pointer şi a operatorului de adresă &.
Revenirea dintr-o funcţie se poate realiza fie prin instrucţiunea return, fie automat
după ultima instrucţiune a funcţiei (situaţie în care nu se returnează nici o valoare):
return [ expresie ] ;
fiind returnată valoarea expresiei (dacă există).
Ex. 1:
#include <graphics.h> #include <math.h>
int u1,v1, u2,v2; float a, b, c, d ;
int u (float x) { return ((x-a)/(b-a)*(u2-u1)+u1); }
int v (float y) { return ((y-d)/(c-d)*(v2-v1)+v1); }
void InitGraf(void) { int Gd = DETECT, Gm; initgraph(&Gd, &Gm, "c:\\Bc\\Bgi"); }
void ViewPort(int x1,int y1,int x2,int y2) {u1=x1; v1=y1; u2=x2; v2=y2; /*rectangle(u1,v1,u2,v2);*/ }
void Window(float x1,float y1,float x2,float y2) { a=x1; d=y1; b=x2; c=y2; }
void Rectangle(float x1,float y1,float x2,float y2) { rectangle(u(x1),v(y1),u(x2),v(y2)); }
void Bar(float x1,float y1,float x2,float y2) { bar(u(x1),v(y1),u(x2),v(y2)); }
void Linie(float x1,float y1,float x2,float y2) { line(u(x1),v(y1),u(x2),v(y2)); }
void Muta(float x,float y) { moveto(u(x),v(y)); }
void Trag(float x,float y) { lineto(u(x),v(y)); }
void Rot(float &x,float &y, float x0, float y0, float Alfa) { float xp;
xp=(x-x0)*cos(Alfa)-(y-y0)*sin(Alfa)+x0;
y =(x-x0)*sin(Alfa)+(y-y0)*cos(Alfa)+y0; x = xp; }
Ex. 2:
// Ultima cifră nenulă a lui n! \\
#include <iostream.h>;
#include <conio.h>;
int Sf (int& f, int k)
26.11.18 18
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
{ int p=0;
while (!(f%k)) { f/=k; p++; }
return p;
}
main () { clrscr(); int n; int f2=0; int Uc=1;
cout << " n : "; cin >> n;
for (int i=2; i<=n; i++) { int f=i;
f2+=Sf(f,2); f2-=Sf(f,5); Uc=Uc*f%10; }
cout << " Uc= " << Uc*((f2&=3,int(f2?f2*1.4:3))<<1)%10;
getch();
}
Ex. 3:
// Calc. AB, AB \\
#include <iostream.h>;
#include <conio.h>;
int Card(int A[])
{
return A[0];
}
int Apart (int x, int A[])
{
for (int i=1; i<=Card(A); i++) if (x==A[i]) return 1; return 0;
}
void n (int A[], int B[], int C[])
{
C[0]=0;
for (int i=1; i<=Card(A); i++) if (Apart(A[i],B)) C[++C[0]]=A[i];
}
void u (int A[], int B[], int C[])
{ int i;
for (i=0; i<=Card(B); i++) C[i]=B[i];
for (i=1; i<=Card(A); i++) if (!Apart(A[i],B)) C[++C[0]]=A[i];
}
void Tip (char *Mult, int A[])
{ int i; cout << Mult << '{' ;
for (i=1; i<=Card(A); i++) cout << A[i] << ",";
cout << "\b}" << endl;
}
void main (void)
{ clrscr();
int A[]={5, 1,3,5,7,9}; Tip (" A : ",A);
int B[]={5, 1,2,3,4,5}; Tip (" B : ",B);
int AuB[10]; u (A,B,AuB); Tip (" AuB = ",AuB);
int AnB[10]; n (A,B,AnB); Tip (" AnB = ",AnB);
getche();
}
26.11.18 19
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
6. Pointeri
O variabilă p de tip pointer conţine adresa unei variabile a cărei valoare se obţine
utilizând operatorul * (*p = valoarea variabilei de la adresa conţinută în p).
Adresa unei variabile v se poate obţine prin operatorul & (&v = adresa variabilei v),
deci putem atribui unui pointer p adresa unei variabile v astfel:
p = &v;
26.11.18 20
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
6.2.1. Incrementare / Decrementare
Aceste operaţii măresc/miocşorează valoarea de adresă spre următorul element (cu o
valoare egală cu lungimea tipului referit):
Var_Pointer + + ; Var_Pointer – – ;
Exemplu:
int Zile[]={31,28,31,30,31,30,31,31,30,31,30,31 }; int *Pointer_Int; int Luna; // 0,1,...,11
printf(" Dati luna (1-12):"); scanf("%d",&Luna);
Pointer_Int=&Zile[Luna]; Pointer_Int--; // &Zile[Luna-1]
printf(" Nr.Zile =%d \n",*Pointer_Int);
6.2.3. Comparare
Doi pointeri ale elementului aceluiaşi tablou pot fi comparaţi utilizând operatorii
relaţionali. Valoarea NULL marchează faptul că un pointer nu referă nici un element.
... p1 < p2 ... ; ... p1 = = p2 ... ; ... p1 != p2 ... ; ... p = = NULL ...;
Exemplu:
int Zile[]={0,31,29,31,30,31,30,31,31,30,31,30,31 }; int *luna; int Zi,Luna,An, NrZile;
printf(" Zi, Luna, An : "); scanf("%d %d %d",&Zi,&Luna,&An);
if (An&3) Zile[2]=28; if ((Zi>Zile[Luna]) || (Luna>12)) luna=NULL; else luna=Zile;
if (luna!=NULL) { NrZile=Zi; do NrZile+=*(luna++); while (luna<Zile+Luna);
printf(" A %d zi a anului \n",NrZile); }
else printf(" Data calendaristica incorecta! \n");
6.2.4. Diferenţă
Diferenţa a doi pointeri ai aceluiaşi tablou dă ca rezultat diferenţa indicilor.
Exemplu:
int Zile[]={0,31,29,31,30,31,30,31,31,30,31,30,31 }; int *luna; int Zi,Luna,An, Ziua;
printf(" An, A câta zi din an:"); scanf("%d %d",&An,&Ziua); if (An&3) Zile[2]=28;
for (luna=Zile+1; Ziua>*luna; luna++) Ziua–=*luna;
printf(" Zi:%d, Luna:%d, An:%d \n",Ziua,luna–Zile,An);
26.11.18 21
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemplu:
// Operaţ ii cu pointeri \\
#include <iostream.h>
#include <conio.h>
void Tip (int *x, int n)
{ int *p=x;
while ( p-x < n ) cout << *(p++); cout << endl;
}
void main (void)
{ clrscr();
int x[]={11,22,33,44,55,66,77}; int *p,*q;
p=x; q=&x[7];
while (q-p) cout << *(p++); cout << endl;
int &f=x[7]; p=&x[0]; q=&f;
while (q>p) cout << *(p++); cout << endl;
p=x;
while (p-x<7) cout << *(p++); cout << endl;
p=x; int n = (sizeof x) / (sizeof (int));
while ( p-x < n ) cout << *(p++); cout << endl;
p=x;
for (int i=1; i<=n; i++) cout << *(p+i-1); cout << endl;
Tip (x,n); getche();
}
26.11.18 22
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Numele unei funcţii fiind un pointer la acea funcţie, ea poate fi parametru actual, şi
evident trebuie descrisă ca parametru formal:
... tip (*f ) ( ), ...
Exemplu:
// Pointeri la func ţii (1) \\
#include <graphics.h> #include <stdlib.h> #include <stdio.h>
#include <conio.h> #include <math.h> #include "Graf.h" #define Pi 3.1415926
float Sin (float x) { return sin (x); } float Cos (float x) { return cos (x); }
float Sqr (float x) { return pow (x,2);} float Sqrt(float x) { return sqrt(x); }
void Grafic(float(*f)(float),float a,float b,int u1,int v1,int u2,int v2)
{ float x, p, c,d, y; ViewPort (u1,v1,u2,v2); rectangle (u1,v1,u2,v2); p=(b-a)/(u2-u1)*5;
x=a; c=d=(*f)(x); do { x+=p; y=(*f)(x); if (y<c) c=y; else if (y>d) d=y; } while (x<b);
Window(a,d,b,c); x=a; MoveTo(x,(*f)(x)); do { x+=p; LineTo(x,(*f)(x)); } while (x<b);
}
void main(void)
{ InitGraph ();
Grafic (Sin, -Pi,Pi,10,10, (int) getmaxx()/2-5, (int) getmaxy()/2-5);
Grafic (Cos, -Pi,Pi,(int) getmaxx()/2+5,10,getmaxx()-10, (int) getmaxy()/2-5);
Grafic (Sqr, -Pi,Pi,10,(int) getmaxy()/2+5, (int) getmaxx()/2-5, getmaxy()-10);
Grafic (Sqrt, 0,Pi,(int) getmaxx()/2+5,(int) getmaxy()/2+5,getmaxx()-10, getmaxy()-10);
getch(); closegraph();
}
26.11.18 23
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
6.5. Utilizarea parametrilor din linia de comandă
Apelul unui program poate fi însoţit de o listă de parametri:
> Nume_Program Listă_Parametri
6.7. S t i va
26.11.18 24
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Prin stivă înţelegem o listă cu disciplina Last In First Out pentru care vom defini
următoarele trei funcţii:
Push - adaugă un element în stivă,
26.11.18 25
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Fact.Cpp \\
// Stiva.h \\
#include <stdio.h>
#include <conio.h> #define DimMax 13
#include "Stiva.h" static int Stiva[DimMax]; static Next=0;
void main(void) void Push(int x)
{
{
if (Next<DimMax) Stiva[Next++]=x;
int n; unsigned long f;
else printf(" Depasire stiva \n");
printf(" Dati n : "); scanf("%d",&n); }
Clear(); while (n) Push(n--); int Pop()
f=1; while (!Vida()) f*=Pop(); { if (Next>0) return Stiva[--Next];
printf(" n! = %15lu \n",f); else { printf(" Stiva vida \n"); return 0; }
getch(); }
} void Clear() { Next=0; }
int Vida() { return (Next= =0); }
7. Recursiviate
Există posibilitatea de a defini o funcţie prin ea însăşi (recursiv).
Exemplu:
#include <conio.h> #include <iostream.h>
#define Max (x,y) (x>y ? x : y)
int a[100];
int Maxim(int n)
{
if (n= =1) return a[1];
else return Max (Maxim(n-1),a[n]);
}
void main(void)
{ int i,n; clrscr();
cout << " Dati n : "; cin >> n;
cout << " Dati A : ";
for (i=1; i<=n; i++) cin >> a[i];
cout << " Max.= " << Maxim(n);
getch();
}
26.11.18 26
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
8. Tipuri de date
Există posibilitatea de a defini noi tipuri de date şi chiar de a le denumi.
Implicit Expr0=0, iar Expri=Expri-1+1, iar dacă se declară o listă de variabile având
acest tip atunci denumirea tipului enumerare definit poate lipsi.
Exemplu:
#include <stdio.h>; // 2003 \\
#include <conio.h>;
enum { False, True } Zi_Lucratoare;
enum ZileSapt { Luni, Marti, Miercuri, Joi, Vineri, Sambata, Duminica };
enum ZileSapt Zi_Sapt; // sau ZileSapt Zi_Sapt;
void main (void)
{
int Zile[]={31,28,31,30,31,30,31,31,30,31,30,31};
int Zi,Luna,luna;
printf(" Zi, Luna : "); scanf("%d %d",&Zi,&Luna);
for (luna=1; luna<Luna; luna++) Zi+=Zile[luna-1];
Zi_Sapt=Luni; Zi=(Zi+1)%7; while (Zi--) Zi_Sapt++; // sau Zi_Sapt=Zi_Sapt+1;
if (Zi_Sapt<Sambata) Zi_Lucratoare=True;
else Zi_Lucratoare=False;
if (Zi_Lucratoare) printf(" Este o zi lucratoare \n");
else printf(" Este o zi libera \n");
getch();
}
26.11.18 27
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
8.3. Definirea unei structuri (struct)
Definirea unei structuri (înregistrări) se face astfel:
struct [Denumire] { Listă_Declaraţii_Câmpuri } [Listă_Var];
Dacă se declară o listă de variabile având acest tip atunci denumirea structurii poate
lipsi.
Referirea componentelor unei structuri se face astfel:
Denumire. Componentă;
Exemplu:
#include <stdio.h>;
#include <conio.h>;
typedef float Real;
struct Punct { Real x, y; };
struct Cerc { Punct Centru;
Real Raza; };
Real Sqr(Real x)
{ return x*x; }
void main (void)
{
Punct O = { 0, 0 }; Cerc C;
printf(" \n Cerc : "); scanf("%f %f %f",&C.Centru.x,&C.Centru.y,&C.Raza);
printf(" \n C(x0,y0,r)= %5.2f %5.2f %5.2f",C.Centru.x,C.Centru.y,C.Raza);
if (Sqr(C.Centru.x-O.x)+Sqr(C.Centru.y-O.y)<=Sqr(C.Raza)) printf(" \n C contine O");
else printf(" \n C nu cont.O");
getch();
}
26.11.18 28
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
8.4. Redefinirea unei date (union)
Redefinirea unei zone de memorie se poate face în cadrul unei uniuni astfel:
union [Denumire] { Listă_Declaraţii } [Listă_Var];
Toate componentele aflate în Listă_Declaraţii ocumă aceeaşi zonă de memorie (se
suprapun), lungimea uniunii fiind dată de maximul lungimilor declaraţiilor .
Referirea componentelor unei uniuni se face astfel:
Denumire. Componentă;
sau pentru o variabilă de tip referinţă:
( *Var_Ref ). Componentă; sau Var_Ref >Componentă;
Exemplu:
...
union U { float Real;
long unsigned Hexa; } x;
int Cifra(int c) { if (c<10) return c|'0'; else return (c-9)|'@'; }
void Cifre(int b) { printf("%c%c",Cifra(b>>4),Cifra(b&0xF)); }
void Print(unsigned x) { Cifre(x>>8); Cifre(x&0xFF); }
void main (void)
{ do { printf(" Dati un numar : "); scanf("%f",&x.Real); printf(" ... Hexa = ");
Print (x.Hexa>>16); Print(x.Hexa&0xFFFF); printf(" ... \n"); }
while (x.Hexa!=0); getch();
}
26.11.18 29
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
9. Structuri de date dinamice
Pentru a implementa structura liniară (lista simplu înlănţuită) şi structura de tip
arbore binar vom apela la structuri definite recursiv.
9.1. Listă simplu înlănţuită ordonată
Considerăm o listă nevidă fiind formată din primul element şi sublista aflată la adresa
de legătură memorată în fiecare element pe lângă informaţia propriuzsă.
În exemplul următor vom crea o listă care va conţine monoamele unui polinom în
ordinea descrescătoare a gradelor. Un element din listă va conţine pe lângă informaţia
propriuzisă (coeficientul şi gradul monomului) şi adresa următorului monom (adresa
sublistei). De exemplu, pentru polinomul P(x)=120x12+77x7+130x3+22x2 lista va conţine
patru elemente având informaţiile (20,12); (77,7); (130,3); (22,2), indiferent de ordinea
introducerii monoamelor. Deoarece coeficienţii sunt nenuli, introducerea datelor se termină
la primul coeficient nul.
#include <stdio.h>
#include <alloc.h>
#include <iostream.h>
#define Nil (NULL)
struct Monom { int Coef, Grad ; };
struct Elem { Monom Inf; Elem* Leg; };
typedef Elem* Polinom; // Listă de monoame ordonate decrescător după grad
int Citit(Monom &M)
{ cin >> M.Coef; if (M.Coef) cin >> M.Grad; return M.Coef;
}
void Ado(Polinom &P, Monom M)
{ int lung=sizeof(Elem); Polinom Nou;
if ((P==Nil)|(P->Inf.Grad<M.Grad)) {Nou=(Polinom) malloc(lung);
Nou->Inf=M; Nou->Leg=P; P=Nou;}
else Ado(P->Leg,M);
}
void Cre(Polinom &P)
{ Monom M; P=Nil;
while (Citit(M)) Ado(P,M);
}
void Tip(Polinom P)
{ if (P!=Nil) { cout << P->Inf.Coef << "X^" << P->Inf.Grad;
if (P->Leg!=Nil) cout << "+" ; Tip (P->Leg); }
}
void main (void)
{ Polinom P;
cout << " P (Coef,Grad) : "; Cre (P);
cout << " Polinomul P(X)="; Tip (P);
getchar();
}
Date : P (Coef,Grad) : 120 12 22 2 77 7 130 3 0
Rezultate : Polinomul P(X)=120X^12+77X^7+130X^3+22X^2
26.11.18 30
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemplu:
// Listă simplă ordonată crescător \\
#include <iostream.h> #include "Crt.Cpp"
typedef int Info;
struct Elem;
typedef Elem* Lista;
struct Elem {Info Inf; Lista Urm;};
int Citit(Info& inf)
{ cin >> inf; return inf; }
void Ado(Lista& L, Info inf)
{ if (L && (L->Inf<inf)) Ado(L->Urm,inf);
// else {Lista Nou=new Elem; Nou->Inf=inf; Nou->Urm=L; L=Nou;} //sau
else {Elem el={inf,L}; Lista Nou = new Elem (el); L=Nou;}
}
void Cre(Lista& L)
{ Info El; L=NULL; while (Citit(El)) Ado(L,El); }
void Tip(Lista L)
{ if (L) {cout << L->Inf << ','; Tip(L->Urm); } cout << "\b."; }
void main (void)
{ ClrScr();
Lista L;
cout << " Lista : "; Cre (L);
cout << " Lista = "; Tip (L); Readln();
}
26.11.18 31
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În exemplul următor se citeste un arbore genealogic ascendent (dând pentru fiecare
persoană nume părinţilor), apoi se va reprezenta grafic arborele construit într-o fereastră
ecran precizată (u1,v1,u2,v2). Distanţa dintre două nivele se calculează ţinând cont de
adâncimea arborelui.
#include <stdio.h>
#include <alloc.h>
#include <string.h>
#include <iostream.h>
#include <graphics.h>
#include <conio.h>
typedef char TInf [13] ;
struct Nod { TInf Inf ; // Radacină \\
Nod* Ls; Nod* Ld; // Sub.St, Sub.Dr
} ;
typedef Nod* Arb;
int Citit(TInf &Inf)
{ cin >> Inf; return (Inf[0]!='.'); }
void Gen(Arb &A)
{ TInf Inf; int Lung=sizeof(Nod);
if (Citit(Inf)) { A=(Arb) malloc(Lung);
strcpy (A->Inf,Inf); // A->Inf=Inf;
cout << " Mama lui " << Inf << " : "; Gen(A->Ls);
cout << " Tatal lui " << Inf << " : "; Gen(A->Ld); }
else A=NULL;
}
void Repr_Grafic(Arb A, int u1, int v1, int u2, int v2, int p)
{ int m;
if (A!=NULL) { m=(u1+u2)/2;
if (v1>20) lineto(m,v1-13);
ellipse(m,v1,0,360,31,13);
outtextxy(m,v1,A->Inf);
moveto(m-2,v1+13);
Repr_Grafic(A->Ls,u1,v1+p,m,v2,p); // St
moveto(m+2,v1+13);
Repr_Grafic(A->Ld,m,v1+p,u2,v2,p); } // Dr
}
int Max (int a, int b)
{ return (a>b ? a : b); }
int Adi(Arb A)
{ if (A==NULL) return -1; else return Max(Adi(A->Ls),Adi(A->Ld))+1; }
void main (void)
{ Arb A;
cout << " Arbore genealogic ascendent pentru : "; Gen (A);
int Gd = DETECT, Gm; initgraph(&Gd, &Gm, "c:\\Bc\\Bgi");
settextjustify(CENTER_TEXT,CENTER_TEXT);
Repr_Grafic(A,50,20,getmaxx()-50,getmaxy()-20,(getmaxy()-40)/Adi(A));
getchar(); closegraph();
}
26.11.18 32
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
10. Utilizarea fişierelor
Prelucrarea fişierelor se poate efectua la două nivele:
Nivelul inferior - face apel direct la sistemul de operare;
Nivelul superior - utilizează proceduri speciale pentru operaţii de intrare/ieşire.
Dacă deschiderea fişierului s-a realizat corect, atunci funcţia returnează o valoare
întreagă reprezentând descriptorul de fişier (LUN, care va fi utilizat în continuare la celelelte
operaţii efectuate asupra acestui fişier), iar în caz de nereuşită se va returna valoarea -1.
Pentru a putea utiliza funcţia Open trebuie incluse fişierele header io.h şi fcntl.h.
Exemplu:
...
int Lun;
Lun = open (“Fisier.Dat”,ORDONLY);
...
26.11.18 33
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
10.1.2. Citirea dintr-un fişier (Read)
26.11.18 34
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemple:
// Creare \\
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
#include <conio.h>
#include <iostream.h>
// Citire \\
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
#include <conio.h>
#include <iostream.h>
26.11.18 35
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
10.2. Nivelul superior
La acest nivel sunt posibile următoarele operaţii:
Funcţia returnează codul caracterului citit, sau valoarea EOF la sfârşitul fişierului,
sau -1 la eroare.
Exemplu:
#include <stdio.h>
void main (void)
{ int c;
while ((c=getc(stdin))!=EOF) putc(c,stdout);
}
26.11.18 36
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
10.2.3. Închiderea unui fişier (FClose)
Ex.2:
// Creare fişier text cu format (articole : (Den, Cant, Preţ)) \\
#include <stdio.h>
#include <conio.h>
void main (void)
{ FILE *Produse; int n=0; int Eof;
char Den[20]; textmode(1);
int Cant; textbackground(BLUE);
float Pret; textcolor(WHITE);
clrscr();
if (Produse=fopen("Fis_Form.Txt","w")) {
do {
printf (" Articolul %d \n",++n);
printf (" - Den. : "); Eof=(scanf("%s",Den)==EOF); if(!Eof){
printf (" - Cant.: "); scanf ("%d",&Cant);
printf (" - Pret : "); scanf ("%f",&Pret);
fprintf(Produse,"%-20s%4d%7.2f\n",Den,Cant,Pret);} }
while (!Eof); fclose (Produse); }
else printf (" Open incorect"); getchar();
}
26.11.18 37
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Listare fişier text \\
#include <stdio.h>
#include <conio.h>
void main (void)
{ FILE *Produse; int n=0;
char Den[20]; textmode(1);
int Cant; textbackground(BLUE);
float Pret; textcolor(WHITE);
clrscr();
if (Produse=fopen("Fis_Form.Txt","r")) {
while (fscanf(Produse,"%s%d%f",Den,&Cant,&Pret)!=EOF) {
printf (" Articolul %d : \n",++n);
printf (" - Den. : %-20s \n",Den);
printf (" - Cant.: %4d \n",Cant);
printf (" - Pret : %7.2f \n",Pret); }
fclose (Produse); }
else printf (" Fisier Absent"); getchar();
}
Fin_Niv_S.Cpp Dictio.Txt
Traduce
Fin_Niv_S.Pas
26.11.18 38
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Traduce Fişier text - String \\
#include <stdio.h> #include <conio.h>
#include <iostream.h> #include <process.h>
#include <string.h>
int Length(char* s)
{ return strlen(s); }
/*
int Pos(char* s, char* S)
{ for (int i=0; i<Length(S); i++) { int Ok=1;
for (int j=0; j<Length(s); j++)
if (S[i+j]!=s[j]) { Ok=0; break; }
if (Ok) return i; } return -1;
} */
int Pos(char* s, char* S)
{
char* p = strstr(S,s); return p ? p-S : -1;
}
/*
void Delete(char* s, int p, int n)
{ while (n) { n--; for (int i=p; i<Length(s); i++) s[i]=s[i+1]; }
} */
void Delete(char* s, int p, int n)
{
for (int i=p; i<Length(s); i++) s[i]=s[i+n];
}
/*
void Insert(char* s, char *S, int p)
{ for (int l=0; l<Length(s); l++) {
for (int i=Length(S); i>=p+l; i--) S[i+1]=S[i]; S[p+l]=s[l]; }
} */
void Insert(char* s, char *S, int p)
{ int m=Length(s); int n=Length(S);
if (p>n) p=n; else if (p<0) p=0;
for (int i=n; i>=p; i--) S[i+m]=S[i];
char* ps=S+p; while (*s) *ps++=*(s++);
}
void Subst (char* x, char* y, char* S)
{ int p=Pos(x,S);
if (p>=0) { Delete(S,p,Length(x)); Insert(y,S,p); }
}
void main (void)
{ clrscr();
const Dd=20; typedef char Cuv[Dd]; struct Per { Cuv St, Dr; };
Per Dictio[20]; int NrCuv=1;
FILE *Dic; Dic=fopen("Dictio.Txt","r");
if (Dic==NULL) { cout << "Dictio ?"; getche(); exit(1); }
while (EOF!=fscanf(Dic,"%s%s",Dictio[NrCuv].St,Dictio[NrCuv].Dr))
cout << NrCuv << " : " << Dictio[NrCuv ].St
<< " -> " << Dictio[NrCuv++].Dr << endl;
fclose(Dic); NrCuv--; getche();
FILE *FisI, *FisE;
FisI=fopen("F_Niv_S.Cpp","r"); FisE=fopen("F_Niv_S.Pas","w");
if (FisI==NULL) { cout << "Fisier ?"; getche(); exit(1); }
const Dm=100; char Rand[Dm];
while (fgets(Rand,Dm,FisI)) { // !=NULL
for (int i=1; i<=NrCuv; i++)
while (Pos(Dictio[i].St,Rand)>=0)
Subst(Dictio[i].St,Dictio[i].Dr,Rand);
fputs(Rand,FisE); cout << Rand; }
fclose(FisI); fclose(FisE); getche();
}
26.11.18 39
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
unde deplasamnet şi origine au aceeaşi semnificaţie ca şi la funcţia lseek.
Funcţia fseek returnează 0 la poziţionare corectă sau o valoare 0 la eroare.
unsigned fwrite (const void *Pzt, unsigned dim, unsigned nrart, FILE * Pf) ;
Ambele funcţii returnează numărul de articole transferate sau -1 la eroare.
Exemple:
#include <stdio.h>
typedef struct { char Den[10];
int Cant;
float Pret;
} Articol;
void main (void)
{ FILE *Pf; Articol Art; int n,i;
if ((Pf=fopen("Fis_Tip.Dat","wb")) == NULL) printf (" Open incorect");
printf ("\n Numarul de articole : "); scanf ("%d",&n);
for (i=1; i<=n; i++) {
printf (" Articolul %d : \n",i);
printf (" - Den. : "); scanf ("%s", Art.Den );
printf (" - Cant.: "); scanf ("%d",&Art.Cant);
printf (" - Pret : "); scanf ("%f",&Art.Pret);
fwrite (&Art,sizeof(Articol),1,Pf); }
fclose (Pf); getchar();
}
...
{...
if ((Pf=fopen("Fis_Tip.Dat","rb")) == NULL) printf (" Open incorect");
...
for (i=1; i<=n; i++) {
fread (&Art,sizeof(Articol),1,Pf);
printf("Articolul %d : \n",i); printf("- Den. : %s\n", Art.Den );
printf("- Cant.: %d\n", Art.Cant); printf("- Pret : %f\n", Art.Pret); } fclose (Pf);
}
26.11.18 40
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
11. Funcţii standard
11.3. Conversii
Funcţiile care urmează (aflate în fişierul stdlib.h) realizează conversii fară format.
26.11.18 41
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
11.4. Funcţii de prelucrare a şirurilor de caractere
Funcţiile din această categorie se află în fişierul string.h.
11.4.1. Copiere (Str[n]Cpy)
char * str[n]cpy (char *destinaţ ie, const char *sursa [, unsigned n ]) ;
unde sursa este copiată în destinaţ ie, eventual doar primii n octeţi (cel mult n).
11.4.2. Concatenare (Str[n]Cat)
char * str[n]cat (char *destinaţ ie, const char *sursa [, unsigned n ]) ;
unde sursa este copiată la sfârşitul destinaţ iei, eventual doar primii n octeţi ai sursei.
11.4.3. Comparare (Str[n][i]Cmp)
int str[n][i]cmp (char *şir 1 , const char *şir 2 [, unsigned n ]) ;
unde şir 1 este comparat cu şir2 (eventual doar primii n octeţi, şi eventual ignorând diferenţa
dintre literele mari şi cele mici), iar rezultatul comparării este un număr negativ dacă
şir1<şir2, este un număr pozitiv dacă şir1>şir2 sau zero dacă şir1=şir2.
26.11.18 42
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
void exit (int cod_retur); termină un program returnând un cod de retur
int system (const char *comandă); execută o comandă şi returnează cod_retur (0=Ok).
Exemplu:
#include <stdio.h>; // Timp : Data, Ora \\
#include <dos.h>;
void main (void)
{ struct date DataC; getdate(&DataC);
struct time OraEx; gettime(&OraEx);
printf(" Data : %2d %2d %4d \n", DataC.da_day,DataC.da_mon,DataC.da_year);
printf(" Ora : %2d:%2d:%2d \n", OraEx.ti_hour,OraEx.ti_min,OraEx.ti_sec);
}
26.11.18 43
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
12. Ecranul în mod text
Există posibilitatea de a defini următoarele moduri de lucru:
void textmode ( int mod ) ;
unde mod poate fi C40 (=1 pentru 40 coloane), C80 (=3 pentru 80 coloane), C4350
(=64 pentru 43/50 linii), şi altele.
Definirea unei ferestre ecran (implicit este tot ecranul) se realizează astfel:
void window ( int u 1 , int v 1 , int u 2 , int v 2 ) ;
Ştergerea unei ferestre ecran:
void clrscr (void) ;
Poziţionarea cursorului:
void gotoxy ( int x, int y) ; // col, lin
Poziţia cursorului:
int wherex ( void ) ; // col
26.11.18 44
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Ieşirea din modul grafic:
void closegraph (void) ;
Setarea / Citirea culorii de fond:
void far setbkcolor (int cul f ) ; / int far getbkcolor (void ) ;
Setarea / Citirea culorii de scriere:
void far setcolor (int cul s ) ; / int far getcolor (void ) ;
Alte funcţii:
Semnifica ţie Funcţii
Număr de pixeli ( Oriz./Vert.) getmaxx (); getmaxy ();
Coordonatele LPR (Ultimul Punct Referit ) getx (); gety ();
Mută LPR (Abs./Rel.) moveto (x,y); moverel (dx,dy);
Trasează segment din LPR lineto (x,y); linerel (dx,dy);
Trasează segment line (x1,y1, x2,y2);
Desenează dreptunghi rectangle (x1,y1, x2,y2);
Desenează cerc circle (x,y,r);
Scrie mesaj [ din LPR ] outtext[xy] ([x,y,] mesaj);
Pagină activă / Pagină vizuală setactivepage (pag); setvisualpage (pag);
Exemple:
#include <graphics.h> // Graficul unei suprafeţe \\
#include "graf.h"
# i n c l u d e < s t d l i b . h > # i n c l u d e < s t d i o . h > # i n c l u d e < con i o. h > # i n c l u d e < m a t h . h >
float Sqr (float x) { return x*x; }
float z (float x, float y) { return sin(Sqr(x)+Sqr(y)); } // z=f(x,y)
void main(void)
{ float x; float y; float px; float py; int i; int j; int n=40; int m=40;
InitGraf (); ViewPort (10,10,getmaxx()-10,getmaxy()-10);
float l=3; float x1=-l; float x2=l; float y1=-l; float y2=l; // Dom (x,y)
DefPr(1./2,1); // DefPr (r,a)
a=PrX(x1,z(x1,y1)); b=a; c=PrY(y1,z(x1,y1)); d=c;
for (i=0; i<=m; i++) for (j=0; j<=n; j++) {
x=x1+(x2-x1)*i/m; y=y1+(y2-y1)*j/n;
px=PrX(x,z(x,y)); py=PrY(y,z(x,y));
if (px<a) a=px; else if (px>b) b=px;
if (py<c) c=py; else if (py>d) d=py;
};
26.11.18 45
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Window(a,d,b,c); setbkcolor(BLUE);
for (i=0; i<=m; i++) {
x=x1+(x2-x1)*i/m; y=y1;
Muta(PrX(x,z(x,y)),PrY(y,z(x,y)));
for (j=1; j<=n; j++) {
y=y1+(y2-y1)*j/n;
Trag(PrX(x,z(x,y)),PrY(y,z(x,y)));
} } setcolor(YELLOW);
for (j=0; j<=n; j++) {
y=y1+(y2-y1)*j/n; x=x1;
Muta(PrX(x,z(x,y)),PrY(y,z(x,y)));
for (i=1; i<=m; i++) {
x=x1+(x2-x1)*i/n;
Trag(PrX(x,z(x,y)),PrY(y,z(x,y)));
} }
getch(); closegraph();
}
// Graf.h \\
#include <graphics.h>
#include <math.h>
26.11.18 46
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
int u1,v1, u2,v2; // ViewPort
float a, b, c, d ; // Window
float Raza, Alfa; // Pr (r,)
int u (float x) { return ((x-a)/(b-a)*(u2-u1)+u1); }
int v (float y) { return ((y-d)/(c-d)*(v2-v1)+v1); }
void InitGraf(void)
{ int Gd = DETECT, Gm; initgraph(&Gd, &Gm, "c:\\Bc\\Bgi"); }
void ViewPort(int x1,int y1,int x2,int y2)
{ u1=x1; v1=y1; u2=x2; v2=y2; /* rectangle(u1,v1,u2,v2);*/ }
void Window(float x1,float y1,float x2,float y2)
{ a=x1; d=y1; b=x2; c=y2; }
void Muta(float x,float y)
{ moveto(u(x),v(y)); }
void Trag(float x,float y)
{ lineto(u(x),v(y)); }
void DefPr(float r, float a)
{ Raza=r; Alfa=a; }
float PrX (float x, float z)
{ return x+Raza*z*cos(Alfa); }
float PrY (float y, float z)
{ return y+Raza*z*sin(Alfa); }
26.11.18 47
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
14. Facilităţi C++
Limbajul C++ oferă în plus faţă de limbajul C unele facilităţi noi. Un avantaj
important îl constituie noţiunea de clasă (prin care se defineşte un TAD), iar acestea pot
forma o ierarhie, deci putem vorbi de o programare orientată obiect.
Dacă în C conversia explicită se poate efectua prin (tip) expresie, în C++ se poate
realiza şi prin tip (expresie).
Exemplu:
#include <stdio.h>; #include <conio.h>;
#include <iostream.h>;
void main (void)
{ char c;
cout << " Dati c : "; cin >> c;
cout << " Car. c = " << c << endl;
cout << " Val. c = " << (int) c << endl;
cout << " Val. c = " << int (c) << endl;
void *p; p=&c;
cout << " Val. c = " << *(int *) p << endl;
typedef int * Pint;
cout << " Val. c = " << * Pint (p)<< endl; // Conţinutul adresei
getch(); // la care se află un întreg
}
26.11.18 48
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
14.2. Operatori
26.11.18 49
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemple:
#include <conio.h>; // Redefinirea unei variabile
#include <iostream.h>;
void main (void)
{ int a[1]; int * b = a; int & c = a[0];
cout << " Dati a : "; cin >> a[0];
cout << " a,b,c = " << a[0] << *b << c << endl;
int x; int * y = &x; int & z = *y; int & w = x;
cout << " Dati x : "; cin >> x;
cout << " x,y,z,w = " << x << *y << z << w << endl; getch();
}
26.11.18 50
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
int *i = new int;
cout << " Dati v : "; cin >> *i;
cout << " v = " << *i << endl;
int *j;
j = new int (*i);
cout << "*i ==*j = " << *j << endl;
delete i;
delete j;
int *r; r = new int [2];
cout << " Dati v1 : "; cin >> * r;
cout << " Dati v2 : "; cin >> *(r+1);
cout << " v1 = " << * r << endl;
cout << " v2 = " << *(r+1)<< endl;
delete r; getch();
}
26.11.18 51
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
14.3. Structură, uniune şi enumerare
Referirea acestor tipuri se poate face în C++ fără a mai fi nevoie de cuvântul
corespunzător struct, union, respectiv enum. De asemenea, parametrii şi valoarea unei
funcţii pot fi structuri, pointeri la structuri sau referinţe la structuri. Sunt permise şi
atribuiri de structuri.
Referirea componentelor unei uniuni anonime din interiorul unei structuri se face la
fel ca şi referirea componentelor structurii, iar prima componentă se poate iniţializa.
În C++, variabilelor de tip enumerare nu se mai pot atribui decât valori ale acestui
tip (nu şi numerele asociate acestor elemente).
Exemple:
#include <stdio.h>; #include <conio.h>; #include <iostream.h>;
typedef float Real;
enum Figura { punct, cerc };
struct Punct { Real x, y; };
struct Cerc { Punct Centru;
Real Raza; };
struct Obiect { Figura FIG;
union { Punct PUNCT;
Cerc CERC;
}; };
Obiect Translatat ( Obiect o, Punct T )
{ o.PUNCT.x = o.PUNCT.x + T.x;
o.PUNCT.y = o.PUNCT.y + T.y;
return o;
}
void main (void)
{ Punct P = { 3,7 };
Obiect O = { punct, { 1,2 } };
Obiect C; C.FIG=cerc; C.CERC.Centru=O.PUNCT; C.CERC.Raza=10;
Obiect D; D=Translatat(C,P);
cout << " D(" << D.CERC.Centru.x << ","
<< D.CERC.Centru.y << ","
<< D.CERC.Raza << ")" << endl; getch();
}
26.11.18 52
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
26.11.18 53
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
15. Funcţii C++
Ex. 2:
#include <iostream.h>;
#define max( x, y) (x>y ? x : y) // Gresit !
inline int Max(int x, int y) // F.Inline
{ return (x>y ? x : y); }
void main (void)
{ int x,y,z;
x=5; y=2; z=max(++x,++y); cout <<" max("<<x<<','<<y<<")="<<z<< endl;
x=5; y=2; z=Max(++x,++y); cout <<" Max("<<x<<','<<y<<")="<<z<< endl;
}
// Rezultatele
max(7,3)=7 !
Max(6,3)=6
26.11.18 54
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
int & Alba_Neagra ( int & Albe, int & Negre ) // Ref. la int
{ if (random(2)) return Albe; // Ref. la Albe
else return Negre; // Ref. la Negre
}
void main (void)
{ int Albe=0; int Negre=0; int i,n; randomize();
cout << "Dati n:"; cin >> n;
for(i=1;i<=n;i++) Alba_Neagra(Albe,Negre)++; // Inc(Albe/Negre)
cout <<"Albe ="<< Albe << endl;
cout <<"Negre="<< Negre<< endl;
getch();
}
26.11.18 55
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Ex. Referinţă \\
#include <iostream.h>; #include "Crt.Cpp"
void suma (int x,int y,int *z)
{ *z = ++x * ++y; }
void Suma (int x,int y,int &z)
{ z = ++x * ++y; }
int* max (int& x, int& y)
{ return ( x > y ? &x : &y ); }
int& Max (int& x, int& y)
{ return ( x > y ? x : y ); }
struct Punct { int x,y; };
Punct Atrib (int x, int y)
{ Punct P; P.x=x; P.y=y; return P; }
Punct sim (Punct P)
{ P.x=-P.x; P.y=-P.y; return P; }
Punct& Sim (Punct& P)
{ P.x=-P.x; P.y=-P.y; return P; }
Punct* Psim(Punct P)
{ P.x=-P.x; P.y=-P.y; return &P; }
void Tip (Punct P)
{ cout << " P(" << P.x << ',' << P.y << ')' << endl; }
void main (void)
{ int x,y,z; ClrScr();
cout << " Dati x,y : "; cin >> x >> y;
suma(x,y,&z); cout << " (x+1)*(y+1) = " << z << endl;
Suma(x,y, z); cout << " (x+1)*(y+1) = " << z << endl;
cout << " x,y = " << x << ' ' << y << endl;
cout << " max(x,y)+1 = " << ++ *max(x,y) << endl;
cout << " x,y = " << x << ' ' << y << endl;
cout << " Max(x,y)+1 = " << ++ Max(x,y) << endl;
cout << " x,y = " << x << ' ' << y << endl;
Punct P=Atrib(x,y); Tip(P);
Tip(sim(P)); Tip(P);
Tip(Sim(P)); Tip(P);
cout <<"P(x,y)=("<< sim(P) .x <<','<< Sim(P) . y <<')'<< endl;
cout <<"P(x,y)=("<<(*Psim(P)).x <<','<< Psim(P)->y <<')'<< endl;
Readln();
} // R e z u l t a t e :
Dati x,y : 1 5
(x+1)*(y+1) = 12
(x+1)*(y+1) = 12
x,y = 1 5
max(x,y)+1 = 6
x,y = 1 6
Max(x,y)+1 = 7
x,y = 1 7
P(1,7)
P(-1,-7)
P(1,7)
P(-1,-7)
P(-1,-7)
P(x,y)=(1,7)
P(x,y)=(-1,-7)
26.11.18 56
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
15.3. Supraîncărcarea funcţiilor
Această proprietate dă posibilitatea utilizării unor funcţii având acelaşi nume, dar
diferite (înrudite, cu antete diferite).
Exemple:
#include <math.h>; #include <complex.h>; #include <conio.h>; #include <iostream.h>;
double ArcTg (double x) { return atan (x); }
double ArcTg (double y, double x) { return atan2(y,x); }
double ArcTg (complex z) { return real (atan(z)); }
void main (void)
{ complex w(1,0);
cout << " Pi = " << 4*ArcTg(1.0) << endl;
cout << " Pi = " << 2*ArcTg(1,0) << endl;
cout << " Pi = " << 4*ArcTg( w ) << endl; getch();
}
26.11.18 57
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În exemplul care urmează se poate vedea cum se pot folosi parametrii impliciţi
pentru a declara punctul O(0,0), un punct A pe axa Ox, un punct P în plan (R2), un cerc C
(în plan), extremităţile unui segment din spaţiu (Q,RR 3), precum şi segmentele QR şi RO:
#include <stdio.h>;
#include <conio.h>;
#include <iostream.h>;
struct Punct { float x,y,z; };
Punct Init( float x0=0, float y0=0, float z0=0 )
{ Punct P;
P.x=x0; P.y=y0; P.z=z0;
return P;
}
void Tip ( Punct P )
{
cout << " P(" << P.x <<','<< P.y <<','<< P.z <<')'<< endl;
}
26.11.18 58
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
struct Segment { Punct A, B; } ;
Segment Init ( Punct A, Punct B = Init() )
{
Segment AB = {{A.x,A.y,A.z},{B.x,B.y,B.z}};
return AB;
}
void Tip ( Segment AB )
{
cout << " Segment : \n"; Tip(AB.A); Tip(AB.B);
}
void main ()
{ clrscr();
Punct O=Init(); Tip(O); // Originea
(0,0,0)
Punct A=Init(7); Tip(A); // A e Ox
(7,0,0)
Punct P=Init(1,2); Tip(P); // P e R2
(1,2,0)
Punct C=Init(3,4,5); Tip(C); // Cerc
(3,4,5)
Punct Q =Init(1,2,3); // Q e R3
Punct R =Init(4,5,6); // R e R3
Segment QR=Init(Q,R); // QR e R3
Tip(QR);
Segment RO=Init(R);
Tip(RO);
getche();
}
26.11.18 59
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
#include <iostream.h>
#include "crt.h"
struct Punct { float x, y;
Punct () { cin >> x >> y; }
void TipP() { cout << x << ' ' << y << endl; }
float D2 () { return x*x + y*y; }
Punct& SimO();
};
Punct& Punct::SimO() { x=-x; y=-y; return *this; }
Punct& ApropO (Punct& P, Punct& Q) { return P.D2()<Q.D2() ? P : Q; }
void main (void)
{ ClrScr();
cout << " P : "; Punct P=Punct();
cout << " Q : "; Punct Q=Punct();
cout << " M = "; ApropO(P,Q).SimO().TipP();
cout << " P = "; P.TipP();
cout << " Q = "; Q.TipP();
Readln()
;
}
Compilare
Program.Cpp Program.Obj
Link-editare
Tad.h Program.Exe
Compilare
Tad.Cpp Program.Obj
26.11.18 60
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În exemplul următor, pentru Tad Mulţime, fişierele vor fi PMult.Cpp, Mult.h şi
Mult.Cpp:
// PMult.Cpp \\
#include <conio.h>
#include <iostream.h>
#include "Mult.h"
void main (void)
{ clrscr();
Multime A, B, C, D;
Init(A); Init(B); Init(C); Init (D);
cout << " A : "; CitM(A);
cout << " A = "; TipM(A);
//cout << "|A|: " << A->card << endl; // Nu se p.!
cout << "|A|: " << Card(A) << endl; // Se p.!
cout << " B : "; CitM(B);
cout << " B = "; TipM(B);
Init(C); Inters(A,B,C); cout << "AnB: "; TipM(C);
Init(D); Reun (A,B,D); cout << "AuB: "; TipM(D);
cout << (Inclus(A,B) ? " A<=B " : " !A<=B ");
cout << (Egale (A,B) ? " A==B " : " A<>B ");
getche();
}
// Mult.h \\
#include "ElMult.h" // Sunt definite elementele mulţimii
struct Cet;
typedef Cet *Multime;
void Init (Multime &A);
int Card (Multime A);
int E_Vida (Multime A);
void Vida (Multime A);
void AdEl (TEl x, Multime A);
void CitM (Multime A);
void TipM (Multime A);
int Apart (TEl x, Multime A);
void Inters (Multime A, Multime B, Multime C);
void Dif (Multime A, Multime B, Multime C);
void Reun (Multime A, Multime B, Multime C);
int Inclus (Multime A, Multime B);
int Egale (Multime A, Multime B);
Multime DifEl (Multime A, TEl a);
Multime Difer (Multime A, Multime B);
// PMult.Cpp \\
#include <iostream.h>
#include <conio.h>
#include "ElMult.h"
#include "Mult.h"
typedef struct Cet { int card;
TEl Elem[Cm];
};
26.11.18 61
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
int Card (Multime A)
{ return A->card; }
void CitM (Multime A)
{ cin >> A->card;
if (Card(A)>Cm-2) cout << Card(A) << Cm << "!"; else
for (int i=1; i<=Card(A); i++) cin >> A->Elem[i];
cout << endl;
}
void TipM (Multime A)
{ for (int i=1; i<=Card(A); i++) cout << A->Elem[i] << ",";
cout << "\b\n";
}
int Apart (TEl x, Multime A)
{ for (int i=1; i<=Card(A); i++) if (x==A->Elem[i]) return 1;
return 0;
}
void Inters (Multime A, Multime B, Multime C)
{ Vida(C);
for (int i=1; i<=Card(A); i++) if (Apart(A->Elem[i],B)) AdEl(A->Elem[i],C);
}
void Dif (Multime A, Multime B, Multime C)
{ int i;
Vida(C);
for (i=1; i<=Card(A); i++) if (!Apart(A->Elem[i],B)) AdEl(A->Elem[i],C);
}
Multime DifEl (Multime A, TEl a)
{
if (Apart(a,A)) { Multime D; Init(D); AdEl(a,D); Dif(A,D,D); return D; }
else return A;
}
Multime Difer (Multime A, Multime B)
{
Multime D; Init(D); Dif(A,B,D); return D;
}
Multime Difer (Multime A, Multime B)
{
Multime D; Init(D); Dif(A,B,D); return D;
}
void Reun (Multime A, Multime B, Multime C)
{ int i;
*C=*A; Multime B_A; Init(B_A); Dif(B,A,B_A);
for (i=1; i<=Card(B_A); i++) AdEl(B_A->Elem[i],C);
// destroy B_A;
}
int Inclus (Multime A, Multime B)
{ int i;
for (i=1; i<=Card(A); i++) if (!Apart(A->Elem[i],B)) return 0; return 1;
}
int Egale (Multime A, Multime B)
{
return Inclus(A,B) && Inclus(B,A);
}
int Egale (Multime A, Multime B)
{
return Inclus(A,B) && Inclus(B,A);
}
26.11.18 62
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
void AdEl(TEl x, Multime A)
{
if (!Apart(x,A))
if (Card(A)>Cm-2) {cout << Card(A) << Cm << "!"; getch();} else
A->Elem[++(A->card)]=x;
}
void Vida(Multime A)
{
A->card=0;
}
void Init(Multime &A)
{
A = new Cet; Vida(A);
}
int E_Vida(Multime A)
{
return (A->card)==0;
}
// ElMult.h \\
#define Cm 255
typedef int TEl; // Tipul elementelor mulţimii
Un tip abstract de dată realizează o unificare (printr-o grupare de tip struct) între
date (date membru) şi operaţiile (funcţii membru) lor caracteristice. Funcţiile membru sunt
considerate de tip inline iar definirea lor în afara structurii se face prin operatorul de
rezoluţie (::). În acest mod însă nu se realizează o protecţie a datelor (accesul la date se
poate face şi prin alte funcţii, nu numai prin cele membru), această protecţie putând fi
realizată (aşa cum vom vedea în cele ce urmează) cu ajutorul claselor.
Exemplu:
#include <stdio.h>; #include <conio.h>; #include <iostream.h>;
#define Pi 3.141592
struct Cerc { float x,y;
float r;
void Init (float x0, float y0, float raza)
{ x=x0; y=y0; r=raza;}
float Lung ();
float Aria ();
};
float Cerc::Lung () { return 2*Pi*r; }
float Cerc::Aria () { return Pi*r*r; }
void main (void)
{ Cerc C; C.Init(1,2,3);
cout << "C(" << C.x << "," << C.y << "," << C.r << ")" << endl;
cout << "Aria = " << C.Aria() << endl;
cout << "Lung = " << C.Lung() << endl; getch();
}
26.11.18 63
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
17. P rogramare o rientată o biect ( O O P )
26.11.18 64
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
17.1. Definirea Claselor
O clasă se declară ca şi o structură, înlocuind cuvântul struct cu class. Protecţia
datelor se defineşte scriind modificatorul dorit (private, protected sau public) urmat de ‘:’.
Descrierea unei clase conţine atât datele membru (variabilele de instanţă) cât şi
funcţiile membru (metodele), precizând pentru acestea gradul de protecţie, astfel:
class Nume_clasă {
{ [ Modificator_de_protecţie: ] Listă_membrii }
};
unde:
Modificator_de_protecţie { private, protected, public} , private fiind implicit,
private nu permite accesul din afara clasei, –
protected permite accesul din clasele derivate, #
public permite accesul din afara clasei; +
Listă_membrii { Listă_declaraţii_date_membru, Listă_ declaraţii _funcţii_membru }
Datele de tip private (–) pot fi accesate doar de funcţiile membru sau funcţii
prietene (friend). O funcţie membru a unei clase poate fi funcţie prietenă a altei clase, iar
dacă toate sunt prietene, atunci se poate declara clasă prietenă (friend). // Vezi C8
Fiecare obiect al unei clase deţine un set de date membru (variabile de instanţă).
Funcţiile membru publice pot fi utilizate din orice funcţie din program, pe când cele
private doar din funcţiile membru ale clasei.
Definirea funcţiilor membru (metodelor) se poate realiza:
a) imediat (complet, antet plus corp) în definiţia clasei (ca funcţie inline) dacă funcţia nu
conţine multe instrucţiuni şi nu conţine structuri repetitive (apelul nu se face prin salt cu
revenire), astfel:
class Nume_clasă { …
Tip_funcţie Nume_metodă ( ... ) { . . . }; // antet+corp
…
};
b) ulterior (dacă a fost declarat în definiţia clasei doar prototipul funcţiei), utilizând
operatorul de rezoluţie (de scop) astfel:
Tip_funcţie Nume_clasă :: Nume_metodă ( ... ) // :: operatorul de
rezoluţie
{ . . . }; // corpul funcţiei
26.11.18 65
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemplu:
// Clasa Punct \\
// ----------------------------- \\
# include <conio.h>
# include <iostream.h>
class Punct { float x, y; // private: (x,y) e
R2
public:
Punct ( ) { x=0; y=0; }
Punct (float x0, float y0) { x=x0; y=y0; }
Punct (Punct& P) { x=P.x; y=P.y; }
void CitP (char* Mes);
void TipP (char* Mes);
Punct& SimPb ( );
};
void Punct::CitP (char* Mes) { cout << Mes; cin >> x >> y ; }
void Punct::TipP (char* Mes) { cout << Mes << x <<' '<< y << endl; }
Punct& Punct::SimPb( ) { float z=x; x=y; y=z; return *this; }
void main (void)
{
. . .
}
Un obiect este o instanţă a unei clase (o variabilă de tipul clasei). Fiecare obiect
aparţine unei singure clase (aceasta putând avea mai multe obiecte).
Obiectele unei clase se declară astfel:
Clasă Listă_Obiecte;
Exemplu:
// Obiecte Punct \\
// ----------------------------- \\
# include <conio.h>
# include <iostream.h>
class Punct {
. . .
};
. . .
void main (void)
{ clrscr(
);
Punct O,A(1,2);
O.TipP(" O = ");
A.TipP(" A = ");
26.11.18 66
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Alocarea (şi iniţializarea) obiectelor se face cu o funcţie membru specifică numită
constructor (cu numele Clasă) iar dealocarea cu o funcţie destructor (cu numele ~Clasă).
Exemplu:
// Constructori - Destructori \\
// ---------------------------- \\
# include <dos.h>
# include <math.h>
# include <conio.h>
# include <graphics.h>
# include <iostream.h>
# define Cale "c:\\BorlandC\\Bgi"
26.11.18 67
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Componentele claselor (datele şi funcţiile membru) se referă prin operatorul sau
>, ca şi în cazul unei structuri. Funcţiile membru referă direct componentele clasei (fără
aceşti operatori, utilizând poinetrul this declarat automat ca pointer la obiectul curent).
Exemplu:
// Operatorii şi > \\
// ---------------------------- \\
# include <dos.h>
# include <math.h>
# include <conio.h>
# include <graphics.h>
# include <iostream.h>
# define Cale "c:\\BorlandC\\Bgi"
Punct* Punct::Transl(const Punct* T){ x+=T >x; y+=T >y; return this; }
26.11.18 68
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
17.2. Constructori şi Destructori
Exemplu:
// Constructori String \\
# include <Conio.h>
# include <String.h>
# include <Iostream.h>
class String { char* s;
public:
String (); // Constructor implicit
String (const String&); // Constructor de copiere
String (const char*); // Constructor de conversie
String& operator=(const String&); // Operator de atribuire
~String (); // Destructor
int Length (); // Lungimea sirului
void Print (); // Tipareste sirul
};
String::String () { s=new char; s[0]=0; }
String::String (const String& S) { s=new char[S.Length( )+1];strcpy(s,S.s);}
String::String (const char* S) { s=new char[ strlen(S)+1];strcpy(s,S); }
String& String::operator=(const String& S)
{ if (s!=S.s) {delete []s; s=new char[S.Length()+1]; strcpy(s,S.s);}
return *this;}
String::~String () { delete []s;}
int String::Length () { return strlen(s); }
void String::Print () { cout << s << endl; }
void main ()
{ clrscr();
String Vid;
Vid.Print ();
String Prop (" Constructori pentru clasa String.");
Prop.Print();
String Rand(Prop);
Rand.Print();
String Rind=Rand;
Rind.Print();
getche();
}
26.11.18 69
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Antetul unui constructor al unei clase ce conţine ca date membru obiecte alte altor
clase este de forma:
Clasă (Listă_par_formali) : Obiect1(Listă_par_formali1),...,Obiectn(Listă_par_formalin)
Exemplu:
#include <stdio.h>; #include <conio.h>; #include <iostream.h>;
class P3D { float x,y,z;
public:
P3D () {x=0;y=0;z=0;}
P3D (float x0, float y0, float z0) {x=x0;y=y0;z=z0;}
void Tip(){ cout <<"P("<<x<<","<<y<<","<<z<<")"<<endl; }
};
class Cerc { P3D x_y_r;
public:
Cerc () { };
Cerc (float x0, float y0, float z0) : x_y_r(x0,y0,z0) { }
Cerc (P3D C) { x_y_r=C; }
Cerc (const Cerc & C0) { x_y_r = C0.x_y_r; }
void Tip(){ cout << " Cerc "; x_y_r.Tip();}
};
void main (void)
{ Cerc O; O.Tip(); // Constructor implicit P3D O(0,0,0)
Cerc C(4,5,6); C.Tip(); // Constructor pentru obiect P3D
P3D P(1,2,3); P.Tip(); // Constructor P3D
Cerc D(P); D.Tip(); // Constructor Cerc
Cerc E(D); E.Tip(); getch(); // Constructor de copiere
}
26.11.18 70
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În exemplul următor se poate urmării momentul în care acţionează constructorul şi
destrucorul:
/ / Obiecte alocate dinamic ( operatorul d e l e t e )
#include <string.h>;
#include <iostream.h>;
Natural::Natural(char* Nr)
{ Numar = new char[strlen(Nr)+1];
strcpy(Numar,Nr);
cout << " Constr.Ob. ..." << Numar << endl;
}
Natural::~Natural()
{ cout << " ... Distr.Ob. " << Numar << endl;
delete Numar;
}
void f(Natural x)
{ cout << " ... f(x) ... " << endl; }
Natural x("123");
// Rezultatele afişate:
Constr.Ob. ...123
*Start*
Constr.Ob. ...456
Constr.Ob. ...789
... f(x) ...
... Distr.Ob. 789
*Stop*
... Distr.Ob. 456
... Distr.Ob. 123
26.11.18 71
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
18. Specificarea claselor – Limbajul UML(Unified Modeling Language)
UML specifică entităţile (clasele) dintr-un program şi relaţiile dintre ele astfel:
Specificarea entităţilor :
numele clasei,
date membru - protecţie nume_dată : tip
funcţii membru - protecţie nume_funcţie (tip par.formali) : tip_funcţie
( protecţie poate fi – (private), # (protected) sau + (public) ).
26.11.18 72
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
19. F u n c ţ i i ş i C l a s e P r i e t e n e ( F r i e n d )
O funcţie este prietenă cu o clasă dacă are acces la datele membru private ale
acelei clase. O funcţie prietenă poate fi o funcţie globală sau chiar o funcţie membru a
altei clase.
O clasă este prietenă cu o altă clasă dacă ea are acces la datele membru ale
acesteia.
O funcţie, respectiv o clasă prietenă se declară utilizând cuvântul friend astfel:
a) friend Tip_funcţie Nume_funcţie ( Listă_parametri_formali ); // Funcţie friend globală
b) friend Tip_funcţie Nume_clasă::Nume_funcţie(Listă_par._formali); // Funcţie friend membru
c) friend Nume_clasă; // Clasă friend
26.11.18 73
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemple:
// Functie globala friend \\
# include <dos.h>
# include <conio.h>
# include <graphics.h>
# include <iostream.h>
# define Cale "c:\\BorlandC\\Bgi"
class Grafic { int Gd, Gm;
public: Grafic(int gd) { Gd=gd; initgraph(&Gd,&Gm,Cale);}
~Grafic( ) { closegraph(); }
};
class Punct { int x, y;
public: Punct (int x0=0,int y0=0) { x=x0; y=y0;
putpixel(x,y,x+y);}
Punct (Punct& P) { x=P.x; y=P.y; }
void Muta () { moveto(x,y); }
void Trag () { lineto(x,y); }
~Punct () { }
friend Punct Mijloc(Punct,Punct); // Functii globale
friend Punct Afin (Punct,Punct,float); // friend
};
Punct Mijloc (Punct A, Punct B) { Punct M (int((A.x+B.x)/2),
int((A.y+B.y)/2));
return M; }
Punct Afin (Punct A, Punct B,float t) { Punct M (int((1-t)*A.x+t*B.x+0.5),
int((1-t)*A.y+t*B.y+0.5));
return M; }
class Segment{Punct A, B; // Capetele Segm.
public:
Segment ( ) : A(), B() { }
Segment (Punct P, Punct Q) { A=P; B=Q;
A.Muta();B.Trag(); }
Segment (Segment& AB) { A=AB.A; B=AB.B; }
~Segment () { A.Muta();B.Trag(); }
Punct Mijlocs () { return Mijloc(A,B);} // ::Mijloc
Punct Afins (float t) { return Afin(A,B,t);} // ::Mijloc
};
void main (void)
{
Grafic Mod(DETECT); setwritemode(XOR_PUT); setbkcolor(BLUE);
Punct* A = new Punct (300,100); // A
Punct* B = new Punct (100,300); // B
Punct* C = new Punct (500,300); // C
Segment* AB = new Segment (*A,*B); // AB
Segment* BC = new Segment (*B,*C); // BC
Segment* CA = new Segment (*C,*A); // CA
for (float Alfa=0; Alfa<1; Alfa+=0.01)
{ Punct* P=new Punct(AB->Afins(Alfa));
Punct* Q=new Punct(CA->Afins(Alfa));
Segment*PQ = new Segment (*P,*Q);
PQ->Mijlocs(); delay(22); // [Punct M=]
delete PQ; delete P; delete Q;
} delete AB; delete A; delete B; getche();
delete BC; delete CA;
}
26.11.18 74
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Functie membru friend \\
# include <dos.h>
# include <math.h>
# include <conio.h>
# include <graphics.h>
# include <iostream.h>
# define Cale "c:\\BorlandC\\Bgi"
float Sqr (int x) { return float(x)*x; }
int Sqrt (float x) { return ceil (sqrt(x)+0.5); }
class Grafic { int Gd, Gm;
public: Grafic(int gd) { Gd=gd; initgraph(&Gd,&Gm,Cale);
setbkcolor(BLUE); }
~Grafic( ) { getche(); closegraph(); }
};
class Punct;
class Segment{Punct *A, *B; // Capetele Segm.
public:
Segment ( ) : A(), B() { }
Segment (Punct*,Punct*);
Segment (Segment&);
~Segment ();
Punct Mijloc ();
};
class Punct { int x, y;
public: Punct (int x0=0,int y0=0) { x=x0; y=y0;
putpixel(x,y,x+y);}
Punct (Punct& P) { x=P.x; y=P.y; }
void Muta () { moveto(x,y); }
void Trag () { lineto(x,y); }
~Punct () { }
friend Punct Segment::Mijloc();
};
Segment:: Segment (Punct *P, Punct *Q) { A=P; B=Q; A->Muta(); B->Trag(); }
Segment:: Segment (Segment& AB) { A=AB.A; B=AB.B; }
Segment::~Segment ( ) { A->Muta(); B->Trag(); }
Punct Segment::Mijloc() { Punct M ( int((A->x+B->x)/2),
int((A->y+B->y)/2));
return M; }
void main (void)
{ Grafic Mod(DETECT); setwritemode(XOR_PUT); int Lung=400;
Punct* O = new Punct; // Originea
Punct* X = new Punct(Lung);
Punct* Y = new Punct(0,Lung);
Segment* OX = new Segment(O,X); // Axa Ox;
Segment* OY = new Segment(O,Y); // Axa Ox;
for (int x=1; x<Lung; x++)
{ Punct* P = new Punct (x);
Punct* Q = new Punct (0,Sqrt(Sqr(Lung)-Sqr(x)));
Segment* PQ = new Segment(P,Q);
PQ->Mijloc(); delay(9);
delete PQ; delete P; delete Q;
} getche();
delete OX; delete OY; delete O; delete X; delete Y;
}
26.11.18 75
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Clasa friend \\
# include <dos.h> # include <math.h> # include <conio.h> # include <graphics.h> # include <iostream.h>
# define Cale "c:\\BorlandC\\Bgi"
struct palettetype pal; float Pi=3.1416, Alfa;
class Grafic { int Gd, Gm;
public: Grafic(int gd) { Gd=gd; initgraph(&Gd,&Gm,Cale);
getpalette(&pal); }
~Grafic( ) { getche(); closegraph(); }
};
class Punct { int x, y;
public: Punct (float x0=0,float y0=0) { x=int(x0);y=int(y0); }
Punct (float x0,float y0,int c)
{x=int(x0+0.5);y=int(y0+0.5);putpixel(x,y,c);}
Punct (Punct& P) { x=P.x; y=P.y; }
void Muta () { moveto(x,y); }
void Trag () { lineto(x,y); }
~Punct () { }
friend Segment;
friend Cerc;
friend Triunghi;
};
class Segment{Punct A, B; int Cul; // Capetele Segm.
public: Segment ( ) : A(), B() { }
Segment (Punct P, Punct Q){ Cul=getcolor();setcolor (Cul);
A=P; B=Q; A.Muta();B.Trag(); }
Segment (Segment& AB) { A=AB.A; B=AB.B; }
~Segment () { setcolor(Cul);A.Muta();B.Trag(); }
Punct Mijloc ();
friend Triunghi;
};
Punct Segment::Mijloc () { Punct M(int((A.x+B.x)/2),int((A.y+B.y)/2)); return M;}
class Cerc { int x, y, r;
public: Cerc (int x0=0,int y0=0,int r0){ x=x0;y=y0;r=r0; circle(x,y,r);}
Cerc (Punct P, int r0) { x=P.x; y=P.y; r=r0; circle(x,y,r);}
Cerc (Cerc& C) { x=C.x; y=C.y; r=C.r; }
Punct PeCerc(float a){ Punct M(x+r*cos(a),y-r*sin(a)); return M;}
~Cerc () { /*circle(x,y,r);*/ }
};
class Triunghi { Punct A, B, C; // Varfuri
public:
Triunghi ( ) : A(), B(), C() { }
Triunghi (Punct,Punct,Punct);
Triunghi (Triunghi& ABC) { A=ABC.A; B=ABC.B; C=ABC.C;}
Punct CentruGr(){ Punct G((A.x+B.x+C.x)/3,(A.y+B.y+C.y)/3,15);
return G; }
~Triunghi (){}
};
Triunghi::Triunghi(Punct P,Punct Q,Punct R) { A=P; B=Q; C=R;
setcolor(YELLOW); Segment AB(A,B); Segment BC(B,C); Segment CA(C,A);
setcolor(LIGHTBLUE); Segment AAP(A,BC.Mijloc());
Segment BBP(B,CA.Mijloc());Segment CCP(C,AB.Mijloc());
int Cf=int((Pi-fabs(Alfa-Pi))/Pi*63); // r g b
setrgbpalette(pal.colors[BLUE], 0, 0, Cf);
setrgbpalette(pal.colors[YELLOW], 63 ,63-Cf,0);
setrgbpalette(pal.colors[LIGHTBLUE], 0, Cf, 63);
setrgbpalette(pal.colors[WHITE], Cf, Cf, Cf);
delay(int(pow((fabs(Alfa-Pi)+0.3)*Pi,2))); }
void main (void)
{ Grafic Mod(DETECT); setwritemode(XOR_PUT); setbkcolor(BLUE);
Punct O(300,250); Cerc c(O,200); // centru, cerc
float uA=Pi/2, uB=Pi+Pi/6, uC=-Pi/4;
for (Alfa=0; Alfa<2*Pi; Alfa+=0.01) {
Triunghi ABC(c.PeCerc(Alfa+uA),c.PeCerc(Alfa+uB),c.PeCerc(Alfa+uC));
ABC.CentruGr(); }
}
26.11.18 76
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
20. M e m b r i s t a t i c i ( S t a t i c ) // $ :
Fiecare obiect dintr-o clasă deţine toate datele membru (atributele) acesteia. Există
însă posibilitatea ca toate instanţele unei clase să deţină anumite atribute comune tuturor
obiectelor clasei respective. Aceşti membri (date, funcţii) statici au acelaşi regim de
protecţie ca şi ceilalţi membrii.
// Membru Static
# include <conio.h>
# include <iostream.h>
26.11.18 77
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
void main (void)
{ Punct A,B; clrscr();
cout << "Initial:" << Punct::Nr_Ob << endl;
for (int i=1; i<=5; i++) {
Punct M(i,i); Punct Q(M);
cout << "i>> "<<i<<":"<< Punct::Nr_Ob <<endl;
if (i%2==0) {
Punct* N=new Punct(i,i); Punct R(*N);
cout <<"i<<"<<i<<":"<< Punct::Nr_Ob <<endl; // Cl::Static.
cout <<"i<<"<<i<<":"<< R .Nr_Ob <<endl; // Ob .Static!
cout <<"i<<"<<i<<":"<< N->Nr_Ob <<endl; // Ob->Static!
delete N;
}
cout << "i..." <<i<< ":"<< Punct::Nr_Ob <<endl; }
cout << "Final..." << Punct::Nr_Ob << endl; getche();
}
În exemplul următor, sunt utilizaţi membri statici a,b,c,d pentru a memora domeniul
minim care conţine toate punctele curbei (definite parametric) care se desenează:
// Membri Statici
# include <math.h> # include <conio.h> # include <graphics.h>
# define Cale "c:\\BorlandC\\Bgi"
class Grafic { int Gd, Gm;
public: Grafic(int gd) { Gd=gd; initgraph(&Gd,&Gm,Cale); setbkcolor(BLUE);}
~Grafic( ) { getche(); closegraph();} };
int u (float);
int v (float);
class Punct { float x, y;
public: Punct () { x=0; y=0; }
void Atrib (float x,float y) { this->x=x; if (x<a) a=x; else
if (x>b) b=x;
this->y=y; if (y<c) c=y; else
if (y>d) d=y; }
Punct (Punct& P) { x=P.x; y=P.y; }
void Muta () { moveto(u(x),v(y)); }
void Trag () { lineto(u(x),v(y)); }
~Punct () { }
static float a,b, c,d; // Fereastra Reală
};
float Punct::a, Punct::d, Punct::b, Punct::c; // Fereastra Reală
int u1=110, v1=20, u2=500, v2=430; // Fereastra Ecran
int u (float x) { return ((x-Punct::a)/(Punct::b-Punct::a)*(u2-u1)+u1); }
int v (float y) { return ((y-Punct::d)/(Punct::c-Punct::d)*(v2-v1)+v1); }
float x (float t) { return cos(2*t)*cos(t); } // x(t)
float y (float t) { return cos(4*t)*sin(t); } // y(t)
void main (void)
{ int i,n=1000; float Pi=3.14153; Grafic Mod(DETECT);
Punct P[1001];
Punct::b=Punct::a=x(0);
Punct::d=Punct::c=y(0);
for (i=0; i<=n; i++) { float Alfa=2*Pi*i/n; P[i].Atrib(x(Alfa),y(Alfa));}
P[0].Muta(); setcolor(WHITE);
for (i=1; i<=n; i++) P[i].Trag();
}
26.11.18 78
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
20.2. Metode (Funcţii membru) Statice // $ :
Metodele (Funcţiile membru) statice, acţionează doar asupra atributelor statice
(ale claselor), deci nu pot acţiona asupra atributelor obiectului curent (deoarece nu li se
transmite poinetrul this). De asemenea ele pot apela doar metodele statice. Pot însă
acţiona asupra atributelor unui anumit obiect prin operatorii sau >. Metodele statice, se
definesc prin specificatorul static astfel:
class Nume_clasă { …
static Tip_funcţie Nume_funcţie ( Listă_par_formali ) … // $ :
…
};
Referirea (utilizarea) metodelor statice se face astfel:
a) … Nume_clasă :: Funcţie_membru (Listă_par_actuali)… // Referire naturală la clasă
b) … Obiect Funcţie_membru (Listă_par_actuali) … // Referire la un obiect
c) … Pointer_Obiect > Funcţie_membru (Listă_par_actuali)… // Referire prin pointer
În următorul exemplu, se determină fereastra reală (definită prin cele două puncte
diagonal opuse St_Sus, Dr_Jos) utilizând funcţiile statice MinX, MaxX, MinY, MaxY pentru a
determina domeniul minimal care include punctele din grafic.
// Funcţii Statice
# include <math.h> # include <conio.h> # include <graphics.h>
# define Cale "c:\\BorlandC\\Bgi"
class Grafic { int Gd, Gm;
public: Grafic(int gd) { Gd=gd; initgraph(&Gd,&Gm,Cale); setbkcolor(BLUE);}
~Grafic( ) { getche(); closegraph();} };
int u (float); int v (float);
class Punct { float x, y;
public: Punct () { x=0; y=0; }
void Atrib (float x,float y){ this->x=x; if (x<MinX()) St_Sus.x=x; else
if (x>MaxX()) Dr_Jos.x=x;
this->y=y; if (y<MinY()) Dr_Jos.y=y; else
if (y>MaxY()) St_Sus.y=y; }
Punct (Punct& P) { x=P.x; y=P.y; }
void Muta () { moveto(u(x),v(y)); }
void Trag () { lineto(u(x),v(y)); }
~Punct () { }
static Punct St_Sus, Dr_Jos; // Fereastra Reala
static float MinX() { return St_Sus.x; } // Metodă Statică
static float MaxX() { return Dr_Jos.x; } // Metodă Statică
static float MinY() { return Dr_Jos.y; } // Metodă Statică
static float MaxY() { return St_Sus.y; } // Metodă Statică
};
Punct Punct::St_Sus, Punct::Dr_Jos; // Fereastra Reala
int u1=110, v1=20, u2=500, v2=430; // Fereastra Ecran
int u (float x) { return ((x-Punct::MinX())/(Punct::MaxX()-Punct::MinX())*(u2-u1)+u1); }
int v (float y) { return ((y-Punct::MaxY())/(Punct::MinY()-Punct::MaxY())*(v2-v1)+v1); }
float x (float t) { return cos(2*t)*cos(t); }// x(t)
float y (float t) { return cos(4*t)*sin(t); }// y(t)
void main (void)
{ int i,n=1000; float Pi=3.14153; Grafic Mod(DETECT);
Punct P[1001]; P[0].Atrib(x(0),y(0));
Punct::St_Sus=Punct::Dr_Jos=P[0];
for (i=1; i<=n; i++) { float Alfa=2*Pi*i/n; P[i].Atrib(x(Alfa),y(Alfa));}
P[0].Muta(); setcolor(WHITE); for (i=1; i<=n; i++) P[i].Trag();
}
26.11.18 79
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Definirea unui pointer la o metodă se poate face astfel:
Tip_funcţie (Nume_clasă :: *Nume_Pointer ) ( Listă_par_formali ) // sau cu typedef
// Pointeri la metode
…
class Punct { float x, y;
public: Punct () { … }
void Atrib …
Punct (Punct& P) {… }
void Muta () { moveto(u(x),v(y)); }
void Trag () { lineto(u(x),v(y)); }
~Punct () { }
static Punct St_Sus, Dr_Jos;
static float MinX() { return St_Sus.x; } // Metodă Statică
…
};
…
// sau:
// void (Punct :: *Pm[2])() = {&Punct::Muta,&Punct::Trag}; // Def+Ini
26.11.18 80
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Un alt exemplu, care utilizează pointeri la metode (Triun, Drept şi Romb) este
următorul:
// Pointeri la *Metode
# include <math.h>
# include <conio.h>
# include <graphics.h>
# define Cale "c:\\BorlandC\\Bgi"
class Grafic { int Gd, Gm;
public: Grafic(int gd) { Gd=gd; initgraph(&Gd,&Gm,Cale); setbkcolor(BLUE);}
~Grafic( ) { getche(); closegraph();} };
int u (float);
int v (float);
class Punct { float x, y;
public: Punct () { x=0; y=0; }
void Atrib (float x,float y) { this->x=x; if (x<MinX()) St_Sus.x=x; else
if (x>MaxX()) Dr_Jos.x=x;
this->y=y; if (y<MinY()) Dr_Jos.y=y; else
if (y>MaxY()) St_Sus.y=y; }
Punct (Punct& P) { x=P.x; y=P.y; }
void Muta () { moveto(u(x),v(y)); }
void Triun () { setcolor(WHITE); Muta();
moverel(0,-3); linerel(-2,5);
linerel(4,0); linerel(-2,-5);}
void Drept () { setcolor(LIGHTRED); Muta();
moverel(-2,-2); linerel(0,4);
linerel(4,0); linerel(0,-4);linerel(-4,0);}
void Romb () { setcolor(YELLOW); Muta();
moverel(0,-3); linerel(-2,3);
linerel(2,3); linerel(2,-3);linerel(-2,-3);}
~Punct () { }
static Punct St_Sus, Dr_Jos; // Fereastra Reala
static float MinX() { return St_Sus.x; }
static float MaxX() { return Dr_Jos.x; }
static float MinY() { return Dr_Jos.y; }
static float MaxY() { return St_Sus.y; }
};
Punct Punct::St_Sus, Punct::Dr_Jos; // Fereastra Reala
int u1=110, v1=20, u2=500, v2=430; // Fereastra Ecran
int u (float x) { return ((x-Punct::MinX())/(Punct::MaxX()-Punct::MinX())*(u2-u1)+u1); }
int v (float y) { return ((y-Punct::MaxY())/(Punct::MinY()-Punct::MaxY())*(v2-v1)+v1); }
float x0 (float t) { return cos(4*t)*cos(t); } // x(t)
float y0 (float t) { return cos(2*t)*sin(t); } // y(t)
float x1 (float t) { return cos(2*t)*cos(t); } // x(t)
float y1 (float t) { return cos(4*t)*sin(t); } // y(t)
float x2 (float t) { return cos(t); } // x(t)
float y2 (float t) { return sin(t); } // y(t)
26.11.18 81
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
22. Supraîncărcarea operatorilor
Anumite operaţii se pot exprima mult mai bine prin operatori. Nu se pot defini
operatori noi, dar se pot supraîncărca cei existenţi ( +, <, ++, +=, >, [ ], ( ), new, delete,
…, mai puţin operatorii *, :: , ?: ), fără a modifica însă aritatea, prioritatea sau
asociativitatea.
Supraîncărcarea se poate face cu:
a) funcţii membru - numărul parametrilor fiind egal cu aritatea operatorului minus unu,
deoarece un operand este chiar obiectul curent pentru care se apelează metoda (acesta
putând fi referit prin pointerul this),
b) funcţii prietene - numărul parametrilor fiind egal cu aritatea operatorului.
Exemplu:
// Op erat ori de c on c at en are + & \\
# include <Conio.h>
# include <String.h> # include <Iostream.h>
class String { char* s;
public:
String (); // Constructor implicit
String (const String&); // Constructor de copiere
String (const char*); // Constructor de conversie
String& operator=(const String&); // Operator de atribuire
String operator+(String&); // Operator + (concatenare) a)
friend String operator&(String&,String&); // Operator & (concatenare) b)
~String (); // Destructor
int Length (); // Lungimea sirului
void Print (); // Tipareste sirul
};
String::String () { s=new char; s[0]=0; }
String::String (const String& S) { s=new char[S.Length( )+1];strcpy(s,S.s);}
String::String (const char* S) { s=new char[ strlen(S)+1];strcpy(s,S); }
String& String::operator=(const String& S)
{ if (s!=S.s) {delete []s; s=new char[S.Length()+1]; strcpy(s,S.s);} return *this; }
String String::operator+(String& S) // funcţie membru a)
{ char* sS=new char[this->Length()+S.Length()+1];
strcpy(sS,s); strcpy(sS+this->Length(),S.s); String Rez(sS); delete sS; return Rez; }
String::~String () { delete []s;}
int String::Length () { return strlen(s); }
String operator&(String& s,String& S) // funcţie prietenă b)
{ char* sS=new char[s.Length()+S.Length()+1];
strcpy(sS,s.s); strcpy(sS+s.Length(),S.s); String Rez(sS); delete sS; return Rez; }
void String::Print () { cout << s << endl; }
void main ()
{ clrscr();
String Nume("Popescu"), Prenume("Ionel");
String Nume_Prenume=Nume+" "+Prenume;
Nume_Prenume.Print();
String Prenume_Nume=Prenume&" "&Nume;
Prenume_Nume.Print(); getche();
}
26.11.18 82
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
22.1. Operatorul de asignare (atribuire) şi iniţializare (=)
Exemplu:
26.11.18 83
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Natural::Natural ( ) { s=new char[2]; s[0]='0'; s[1]=0; }
Natural::Natural (const Natural& S)
{ s=new char[strlen(S.s)+1];strcpy(s,S.s);}
Natural::Natural (unsigned long S)
{ int n=Lung(S); s=new char[n+1]; s[n]=0;
for(int i=n-1;i>=0;i--) {s[i]=S%10+48; S/=10;} }
Natural& Natural::operator = (const Natural& S)
{ if (s!=S.s) { delete []s; s=new char[strlen(S.s)+1]; strcpy(s,S.s);}
return *this; }
char* Suma (const char*, const char*);
Natural Natural::operator + (const Natural& S)
{ Natural Sum; Sum.s=Suma(s,S.s); return Sum; }
char* Dif(const char*, const char*);
Natural Natural::operator - (const Natural& S)
{ Natural D; D.s=Dif(s,S.s); return D; }
int Natural::operator< (const Natural& S)
{ if (strlen(s)<strlen(S.s)) return 1; else
if (strlen(s)>strlen(S.s)) return 0; else return strcmp(s,S.s)<0; }
int Natural::operator<=(const Natural& S) { return !(*this>S); }
int Natural::operator> (const Natural& S) { return S< *this; }
int Natural::operator>=(const Natural& S) { return S<=*this; }
int Natural::operator==(const Natural& S) { return strcmp(s,S.s)==0; }
int Natural::operator!=(const Natural& S) { return strcmp(s,S.s)!=0; }
int Natural:: Length () { return strlen(s); }
void Natural:: Print () { cout << s << endl; }
void Natural:: Input () { char* x=new char[100]; cin >> x;
delete []s; s=new char[strlen(x)+1];
strcpy(s,x); delete x; }
Natural::~Natural() { delete []s; }
int Natural::Lung(unsigned long n)
{ if (n<10) return 1; else return Lung(n/10)+1;}
char* Suma (const char* a, const char *b)
{ int m=strlen(a), n=strlen(b), i=m-1, j=n-1, t=0; if (m<n) return Suma(b,a);
char* c=new char[m+1]; c[m]=0;
for ( ; i>=0; i--) {
if (j>=0) c[i]=a[i]+b[j]+t-48; else c[i]=a[i]+t;
if(c[i]>'9'){ c[i]-=10; t=1 ; } else t=0; j--; }
if (!t) return c;
char* d=new char[m+2]; for (i=0,d[0]='1'; i<=m; i++) d[i+1]=c[i];
delete []c; return d;
}
char* Dif (const char* a, const char *b)
{ int m=strlen(a), n=strlen(b), i=m-1, j=n-1, t=0;
char* c=new char[m+1]; c[m]=0;
for ( ; i>=0; i--) {
if (j>=0) c[i]=a[i]-b[j]-t+48; else c[i]=a[i]-t;
if(c[i]<'0'){ c[i]+=10; t=1 ; } else t=0; j--; }
char *d=c; while((*d=='0') && *(d+1)) d++;
strcpy(c,d); return c;
}
void main ()
{ clrscr();
Natural a,b;
cout << " a : "; a.Input();
cout << " b : "; b.Input();
26.11.18 84
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
22.2. Operatorii de atribuire += , = , * = , /=
Aceşti operatori (+=, =, *=, /=) nu sunt supraîncărcaţi automat, deci dacă dorim
să-i utilizăm va trebui să îi redefinim (aşa cum se poate vedea în exemplul următor
supraîncărcarea operatorilor +=, =).
Exemplu:
// C l asa Nu m ar Nat u ral (Op. +=, -= ) \\
# include <Conio.h>
# include <String.h> # include <Iostream.h>
class Natural { char* s;
int Lung(unsigned long);
public:
Natural ( ); // Constructor implicit
Natural (const Natural&); // ... de copiere
Natural (unsigned long); // ... de conversie
Natural& operator= (const Natural&); // Operator de atribuire
Natural operator+ (const Natural&); // Operator de adunare
Natural operator- (const Natural&); // Operator de scadere
Natural& operator+=(Natural&); // ... de ad.&.atr.
Natural& operator-=(Natural&); // ... de sc.&.atr.
int operator< (const Natural&); // ... relational <
int operator<=(const Natural&); // ... ... <=
int operator> (const Natural&); // ... ... >
int operator>=(const Natural&); // ... ... >=
int operator==(const Natural&); // ... ... ==
int operator!=(const Natural&); // ... ... <>
~Natural (); // Destructor
int Length (); // Numarul de cifre
void Print (); // Tipareste numar
};
Natural::Natural ( ) { … }
Natural::Natural (const Natural& S) { … }
Natural::Natural (unsigned long S) { … }
Natural& Natural::operator= (const Natural& S){ … }
char* Suma (const char* a, const char *b) { … }
char* Dif (const char* a, const char *b) { … }
Natural Natural::operator+ (const Natural& S){ Natural Sum; Sum.s=Suma(s,S.s); return Sum;}
Natural Natural::operator- (const Natural& S){ Natural D; D.s=Dif(s,S.s); return D;}
Natural& Natural::operator +=(Natural& S){return *this = *this + S;}
Natural& Natural::operator -=(Natural& S){return *this = *this - S;}
int Natural::operator< (const Natural& S) { … }
int Natural::operator<=(const Natural& S) { … }
int Natural::operator> (const Natural& S) { … }
int Natural::operator>=(const Natural& S) { … }
int Natural::operator==(const Natural& S) { … }
int Natural::operator!=(const Natural& S) { … }
int Natural:: Length () { … }
void Natural:: Print () { … }
Natural::~Natural() { … }
int Natural::Lung(unsigned long n) { … }
void main ()
{ Natural a(125),b(175); clrscr();
while (a!=b) if (a>b) a-=b; else b-=a;
if (a==1) cout << " Prime intre ele ";
else { cout << "Cmmdc="; a.Print(); } getche();
}
26.11.18 85
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
22.3. Operatorii de incrementare (++) şi decrementare ( )
Continuând cu exemplul anterior, dorim să suparaîncărcăm operatorii de
incrementare si decrementare, mai întâi cei prefixaţi (++x, x), unde nu sunt probleme
deosebite, apoi ce postfixaţi (x++, x). Pentru a supraîncărca şi operatorii de
incrementare postfixaţi vom adăuga câte o funcţie membru având un parametru de tip int
(care nu se va folosi, şi care automat la un apel va lua valoarea zero).
Exemplu:
// C l asa Nu m ar Nat u ral (Op . ++x, - - x, x+ +, x- -) \\
# include <Conio.h>
# include <String.h> # include <Iostream.h>
class Natural { char* s;
int Lung(unsigned long);
public:
Natural ( ); // Constructor implicit
Natural (const Natural&); // ... de copiere
Natural (unsigned long); // ... de conversie
Natural& operator= (const Natural&); // Operator de atribuire
Natural operator+ (const Natural&); // Operator de adunare
Natural operator- (const Natural&); // Operator de scadere
Natural& operator ++(); // ... prefixat incr
Natural operator ++(int); // ... postfixat ...
Natural& operator --(); // ... prefixat decr
Natural operator --(int); // ... postfixat ...
int operator < (const Natural&); // ... relational <
~Natural (); // Destructor
int Length (); // Numarul de cifre
ostream& Tip (ostream& S); // cout << x…
istream& Cit (istream& S); // cin >> x…
};
Natural::Natural ( ) { … }
Natural::Natural (const Natural& S) { … }
Natural::Natural (unsigned long S) { … }
Natural& Natural::operator= (const Natural& S){ … }
…
Natural Natural::operator+(const Natural& S) { … }
Natural Natural::operator-(const Natural& S) { … }
int Natural::operator< (const Natural& S) { … }
Natural::~Natural() { … }
Natural& Natural::operator++() { return *this=*this+1; } // ++x
Natural& Natural::operator--() { return *this=*this-1; } // --x
Natural Natural::operator++(int){ Natural x(*this); *this=*this+1; return x;} // x++
Natural Natural::operator--(int){ Natural x(*this); *this=*this-1; return x;} // x--
ostream& Natural::Tip (ostream& S) { S << s; return S; } // cout
istream& Natural::Cit (istream& S) { char* x=new char[256]; S>>x; delete[]s;
s=new char[strlen(x)+1]; strcpy(s,x); delete x; return S; } // cin
ostream& operator << ( ostream& S, Natural s ) { return s.Tip(S); } // <<
istream& operator >> ( istream& S, Natural& s ) { return s.Cit(S); } // >>
void main ()
{ Natural i, n=1001, k; clrscr();
cout << " Limita : "; cin >> k;
for (i=101; i<n; i++) if (i<k) cout << i << endl; getche();
}
26.11.18 86
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
23. Conversii utilizator
Conversiile sunt executate automat dacă:
a) operanzii nu sunt de acelaşi tip (char, enum int double, ..., iar la atribuire se face
conversia valoarii expresiei în tipul variabilei);
b) parametrul actual nu are tipul parametrului formal (se face conversia primului);
c) tipul valorii returnate de o funcţie diferă de tipul acesteia (se face conversia valorii).
26.11.18 87
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
O altă variantă în care se evită utilizarea unei funcţii prietene este de a defini o funcţie
membru (Produs) care se va apela de către funcţia de supraîncărcare a operatorului de
înmulţire.
Exemplu:
/ / N u m e re r a ţ i o n a l e : Q
#include <string.h>; #include <iostream.h>; #include <conio.h>;
long Cmmdc(long, long);
class Q { long m; long n; // m / n
public: Q (long, long); // constr. implicit
Q& operator ~(); // operator de simplificare
Q Produs (Q); // Produs
void Tip(const char* Mes=""); // tiparire (mesaj)
};
inline Q::Q(long p=0, long q=1 ) { m=p; n=q; }
Q& Q::operator ~()
{ long d=Cmmdc(m,n); m/=d; n/=d; return *this; }
inline Q Q::Produs (Q r) { return ~Q(m*r.m, n*r.n); }
Q operator *(Q p, Q q) { return p.Produs(q); } // operator de inmultire
inline void Q::Tip (const char* Mes)
{ if (n) cout << Mes << m << "/" << n << endl; else cerr << " Numitor nul " ;};
long Cmmdc(long a, long b) { if (b) return Cmmdc(b,a%b); else return a; };
void main ()
{ clrscr();
Q x(3,2); x.Tip(" x : ");
Q y(2,9); y.Tip(" y : ");
Q z(4,2); z.Tip(" z : ");
Q w;
w=x*y; w.Tip(" x*y= ");
w=x*z; w.Tip(" x*z= ");
w=x*2; w.Tip(" x*2= ");
w=2*x; w.Tip(" 2*x= "); getch();
} // R e z u l t a t e :
x : 3/2
y : 2/9
z : 4/2
x*y= 1/3
x*z= 3/1
x*2= 3/1
2*x= 3/1
26.11.18 88
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemplu:
/ / N u m e re c o m p l e x e : T C
#include <iostream.h> #include <conio.h> #include <math.h>
#include <complex.h>
// class C;
class T { float Ro, Fi; // forma polara
public: T (float Modul=0, float Arg=0);
// T (C w); // Conversie C->T
float Re ();
float Im ();
void Tip (const char* Mesaj);
};
class C { float Re, Im; // forma algebrica
public: C (float a=0, float b=0);
C (T z); // Conversie prin constructor C<-T
float Modul ();
float Arg ();
void Tip (const char* Mesaj);
};
C::C ( float a, float b ) { Re=a; Im=b; }
C::C (T z) { Re=z.Re(); Im=z.Im(); } // Conversie prin constructor C<-T
float C::Modul( ) { return sqrt(Re*Re+Im*Im); }
float C::Arg ( ) { return atan2 (Im,Re); }
float C::Arg ( ) { return atan2 (Im,Re); }
void C::Tip ( const char* Mesaj)
{ cout << Mesaj << Re << "+" << Im << "i" << endl; }
26.11.18 89
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
23.2. Conversii explicite
} // R e z u l t a t e :
z = 6/35
a = 1.8
b = 1.8
26.11.18 90
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
23.2.2. Conversia dintr-un tip abstract într-un alt tip abstract (prin operatori)
Acest tip de conversie se poate realiza şi prin oparatori (dar nu simultan şi prin
constructori). În programul următor este realizată conversia (prin operatorul de
conversie) din trigonometrică (clasa T) în forma algebrică (clasa C):
/ / N u m e re c o m p l e x e : T C
#include <iostream.h> #include <conio.h> #include <math.h>
#include <complex.h>
class C { float Re, Im; // forma algebrică
public: C (float a=0, float b=0);
float Modul ();
float Arg ();
void Tip (const char* Mesaj);
};
C::C ( float a, float b ) { Re=a; Im=b; }
float C::Modul( ) { return sqrt(Re*Re+Im*Im); }
float C::Arg ( ) { return atan2 (Im,Re); }
void C::Tip ( const char* Mesaj)
{ cout << Mesaj << Re << "+" << Im << "i" << endl; }
26.11.18 91
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
24. Clase Şablon (Template)
Exemplu:
// Funcţii T e m p l a t e (1) \\
#include <iostream.h>
#include <conio.h>
template <class T>
T Max (T x, T y) { return (x>y)? x : y; }
void main ()
{ clrscr();
int a,b;
cout << " Dati a,b : "; cin >> a >> b;
cout << " Maximul = " << Max(a,b) << endl;
float x,y;
cout << " Dati x,y : "; cin >> x >> y;
cout << " Maximul = " << Max(x,y) << endl;
getche();
} //N&d-Eusorsăgreşeşti!
26.11.18 92
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
24.2. Clase Template
O clasă Template este un model (şablon) din care se vor genera diverse clase
concrete prin particularizarea atributelor cu tip ambiguu (generic). O astfel de categorie de
clase care diferă prin tipurile atributelor sunt specificate printr-o clasă template pentru ca
apoi să fie generate diverse clase specifice corespunzătoare anumitor tipuri necesare
aplicaţiei.
Exemplu:
// Clase T e m p l a t e \\
#include <iostream.h>
#include <conio.h>
template <class T>
class Vect { T* X;
int Dim;
public: Vect (int n) { X = new T [Dim=n]; }
~Vect ( ) { delete [ ] X; }
void CitV ( );
T MaxV ( );
};
template <class T>
void Vect<T>::CitV ()
{
for (int i=0; i<Dim; i++) cin >> X[i];
}
template <class T>
T Vect<T>::MaxV ()
{ T max=X[0];
for (int i=1; i<Dim; i++)
if (X[i]>max) max=X[i];
return max;
}
void main ()
{ clrscr();
int m;
cout << " Dati nr.el. X : "; cin >> m;
Vect<int> X(m);
cout << " Dati elem. X : "; X.CitV();
cout << " Maximul este " << X.MaxV() << endl;
int n;
cout << " Dati nr.el. Y : "; cin >> n;
Vect<float> Y(n);
cout << " Dati elem. Y : "; Y.CitV();
cout << " Maximul este " << Y.MaxV() << endl; getche();
}
26.11.18 93
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
24.3. Implementarea elementelor Template
În cele ce urmează ne vom referi la poziţia codului (care se expandează conform
cerinţelor utilizatorului) corespunzător obiectelor template. Codul template (corpul
funcţiilor membru) trebuie să fie vizibil acolo unde sunt utilizate elemente template.
Există două metode (posibilităţi) de implementare:
a) template smart – tot codul unei clase template este scris în fişierul header (definiţii de
clase, funcţii precum şi implementarea funcţiilor), acest mod putând fi precizat fie prin
opţiunea de compilare –Jg, fie prin meniul Options , Compiler , C ++ options ,
opţiunea Template Generation : Smart , programul urmând să includă acest fişier cu
toate descrierile.
b) template manual – doar declaraţiile elementelor template sunt scrise în fişierul header
iar implemetarea făcându-se separat, în alt fişier. Acest mod trebuie precizat prin
directiva #pragma option, utilizând opţiunea de compilare –Jgd (urmează o definire
publică a instanţierilor unor elemente template) şi opţiunea –Jgx (urmează o declaraţie
externă a instanţierilor template). Acest mod este ilustrat în următorul exemplu simplu:
// Program Template ... Manual \\
#include <conio.h> #include <iostream.h>
# include "C_Templ4.h"
# pragma option -Jgx
void main ()
{ clrscr();
Vint10 X; X.CitV("X"); cout << " Maximul este " << X.MaxV( ) << endl;
Vflo13 Y; Y.CitV("Y"); cout << " Maximul este " << Y.MaxV( ) << endl; getche();
}
26.11.18 94
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
25. Relaţii între clase
simplă multiplă k
C1 C2 C1 C2
2) Agregare – relaţie de asociaţie prin care obiectul agregat este inclus în obiectul
agregant (verbul caracteristic este a avea), şi evident că poate fi simplă sau multiplă:
simplă multiplă k
C1 C2 C1 C2
C1 C1 C1 C2
C2 C2 C3 C3
26.11.18 95
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
25.1. Relaţia de Asociaţie
instanţiere
C1 asociaţie C2
(care depind unul de celălalt). Traversarea unei C1 C2
rol1 rol2
asociaţii se face printr-un rol (nume dat
extremitatăţii unei asociaţii). Implementarea unei
instanţiere
asociaţii se poate realiza astfel:
a) printr-un pointer – clasa asociantă conţine
un atribut de tip pointer spre clasa asociată,
b) printr-o clasă – cu atribute şi comportare legătură
proprie, fiecare legătură fiind o instanţă a O1 O2
acestei clase.
Asociaţiile pot fi unidirecţionale sau bidirecţionale, iar relaţiile de asociaţie pot fi
binare, ternare sau n-are. Pe de altă parte, asociaţiile pot fi simple sau multiplicative
(acestea din urmă putând fi eventual şi cu restricţii de ordonare sau de calificare).
Asociaţiile multiplicative sunt caracterizate prin numărul de instanţe ale claselor
care se află în asociaţie, iar pentru a reprezenta direcţia de asociaţie se pot utiliza săgeţi.
O asociaţie multiplicativă poate să fie
asociaţia {ordonata}
neordonată (instanţele formează o mulţime), sau C1 C2
poate să fie ordonată (instanţele formează o listă
ordonată).
O relaţie multiplicativă cu restricţie de
calificare pune în relaţie două clase printr-un
asociaţia
calificant (atribut care reduce multiplicitatea C1 calificant C2
asociaţiei printr-un criteriu pe care trebuie să-l
îndeplinească obiectele asociate pentru a intra în
relaţie).
La implementarea relaţiilor de asociaţie putem aplica cele două metode amintite
anterior:
a) prin pointeri spre clasa asociată încuibăriţi în clasa asociantă în funcţie de tipul relaţiei
de asociere astfel:
– pentru relaţia de asociaţie simplă se adaugă clasei asociante încă un atribut de tip
pointer spre clasa asociată, împreună cu relaxarea încapsulării pentru traversarea
asociaţiei alegând o metodă convenabilă dintre următoarele variante:
modificarea protecţiei datelor membru implicate în public,
utilizarea de metode sau clase friend,
extinderea interfeţei prin metode de acces la componente.
– pentru relaţia de asociaţie multiplă se adaugă clasei asociante mai multe atribute de tip
pointer în funcţie de tipul asociaţiei şi ordinul de multiplicitate astfel:
dacă este relativ mic, se vor adăuga pointeri distincţi,
iar în caz contrar se poate utiliza un şir de pointeri;
dacă relaţia este supusă unor restricţii de ordonare, se pot utiliza liste ordonate.
26.11.18 96
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
b) prin clase distincte care realizează
abstractizarea asociaţiilor dacă legăturile au
m n
proprietăţi şi operaţii proprii (nemaifiind C1 C2
necesară adăugarea de atribute claselor care se
asociază), această metodă utilizându-se în Cas.
special în cazul asociaţiilor bidirecţionale de tip
m-n), sau o legătură poate conecta obiecte de
clase diferite.
Exemplu:
// Clase asociate \\
#include <conio.h>
#include <iostream.h>
#include "VectCaut.h"
void main (void)
{ int n; clrscr();
cout << " Dati n : "; cin >> n;
VectSort X(n); // X.Sort ();
VectCaut x(&X); X.Print();
int a,p;
do { cout << " Dati a : "; cin >> a;
if (p=x.CautSec(a)) cout << " Pe poz." << p << endl;
else if(a) cout << " Inexistent! " << endl; }
while (a);
cout << " Dati m : "; cin >> n;
VectSort* Y=new VectSort(n); Y->Sort();
VectCaut* y=new VectCaut(Y); Y->Print();
do { cout << " Dati b : "; cin >> a;
if (p=y->CautBin(a)) cout << " Pe poz." << p << endl;
else if(a) cout << " Inexistent! " << endl; }
while (a); getche();
}
26.11.18 97
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Clasă asociantă \\ << VectCaut.Cpp >>
# include "VectCaut.h"
VectCaut::VectCaut (VectSort *p)
{
v = p;
}
int VectCaut::CautSec(int a)
{ int i=1, n=v->Dim(), *x=v->Adr();
while ((i<=n) && (x[i]-a)) i++;
return i%(n+1);
}
int VectCaut::CautBin(int a)
{ int St=1, Dr=v->Dim(), *x=v->Adr();
while (St<=Dr) { int m=(St+Dr)/2;
if (x[m]-a) if (x[m]<a) St=m+1; else Dr=m-1;
else return m; }
return 0;
}
int VectSort::Dim ( )
{
return n;
}
VectSort::~VectSort ( )
{
delete []v;
}
26.11.18 98
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
25.2. Relaţia de Agregare
instanţiere
componentă a altei clase, deci relaţia este binară, C1 Conţine C2
C1 C2
unidirecţională, iar relaţiile multiplicative sunt de
tip 1-n. Prin această relaţie dintre clase, un obiect
instanţiere
al clasei agregate este parte constituentă, atribut,
al clasei agregante, deci verbul caracteristic este a
avea (conţine). Obiectele constituente pot fi
independente sau doar componente ale obiectului
conţine
care le include. O1 O2
Exemplu:
// Relaţia de agregare \\
#include <conio.h>
#include <iostream.h>
#include "Vect_Agr.h"
void main (void)
{ int n; clrscr();
cout << " Dati n : "; cin >> n;
VectCaut X(n); X.Print();
int a,p;
do { cout << " Dati a : "; cin >> a;
if (p=X.CautSec(a)) cout << " Pe poz." << p << endl;
else if(a) cout << " Inexistent! " << endl; }
while (a);
cout << " Dati m : "; cin >> n;
VectCaut* Y=new VectCaut(n); Y->Sort(); Y->Print();
do { cout << " Dati b : "; cin >> a;
if (p=Y->CautBin(a)) cout << " Pe poz." << p << endl;
else if(a) cout << " Inexistent! " << endl; }
while (a); getche();
}
26.11.18 99
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Clasă Agregantă \\ << Vect_Agr.h >>
#include "VectSort.h"
class VectCaut { VectSort V;
public: VectCaut (int=10);
void Sort ();
void Print();
int CautSec (int);
int CautBin (int);
};
26.11.18 100
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În următorul exemplu se va folosi o clasă Iterator pentru listă simplu înlănţuită care
utilizează clasa Elem pentru un nod al listei şi clasa Lista:
// Iterator Listă \\
#include <conio.h>
#include <iostream.h>
26.11.18 101
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
25.3. Clase Încuibate(imbricate)
Există posibilitatea definirii unei clase (încuibate) în interiorul altei clase (ca şi
atribut al cesteia). Această posibilitate există de fapt şi la structuri (struct) şi uniuni (union).
Declararea obiectelor din clasa încuibată se poate realiza utilizând operatorul de
scop (::) aşa cum se poate vedea în exemplul următor:
// C l as e Im bri ca t e \\
class Cerc { // Cerc(x,y,r)
float r; // Raza
class Punct { // Punct(x,y) Centrul
float x,y; /*
... */
}; /*
... */
};
void main ()
{
Cerc C;
Cerc::Punct P;
// ...
}
// C l as e In cu i b at e \\
#include <conio.h>
#include <iostream.h>
class Cerc { // Cerc(x,y,r)
float r;
class Punct { // Punct(x,y)
float x,y;
public: Punct (float x0=0, float y0=0) { x=x0; y=y0; }
void Print () { cout <<' '<< x <<' '<< y <<' '; }
};
Punct Centru;
public: Cerc (Punct P, float raza) { Centru=P; r=raza; }
void Print() { Centru.Print(); cout << r; }
};
void main ()
{ clrscr();
Cerc::Punct O(1,2); O.Print(); cout << endl;
Cerc C(O,3); C.Print(); cout << endl;
getch();
}
26.11.18 102
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Evident că din clasa încuibată (Punct) nu avem acces la elementele clasei din care
face parte (Cerc). Dacă se doreşte acest lucru, atunci se poate proceda ca şi în următorul
exemplu:
// C l as e In cu i b at e \\
#include <conio.h>
#include <iostream.h>
class Cerc { // Cerc(x,y,r)
float r;
public: Cerc (float raza) { r=raza; }
class Punct;
friend Punct;
class Punct { // Punct(x,y)
float x,y;
public: Punct (float x0, float y0) { x=x0; y=y0; }
void Print (Cerc c){cout <<' '<<x<<' '<<y<<'
'<<c.r;}
}; };
void main ()
{ clrscr();
Cerc c(3);
Cerc::Punct O(1,2); O.Print(c);
getch();
}
26.11.18 103
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
25.4. Relaţia de derivare
Prin această relaţie putem modela similitudinile dintre clase două sau mai multe
clase. Pornind de la o clasă de bază (generală) se pot deriva noi clase (prin diferenţele
specifice). Obiectele clasei derivate moştenesc atributele şi metodele clasei de bază la care
se vor adăuga noile elemente caracteristice (vor fi umflate), ceea ce permite reutilizarea
resurselor deja pregătite în clasele de bază (pentru obiectele similare). Verbul caracteristic
al acestei relaţii de specializare este a fi ( … este un fel de … <a kind of>).
Moştenirea permite păstrarea elementelor (date şi
funcţii ale) unei clase de bază (superclasă), cu definirea de
noi elemente construind o nouă clasă derivată (subclasă),
este un …
formând în felul acesta ierarhii de clase. Moştenirea poate fi Ob
şi multiplă dacă o clasă moşteneşte mai multe clase.
Deoarece această relaţie este tranzitivă se utilizează şi
este o …
Cb
termenii de strămoş şi descendent.
generalizare
Od
C1 C1 C1 C2
specializare
Cd
C2 C2 C3 C3
26.11.18 104
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Lista claselor de bază poate să conţină şi modificatorii de protecţie (Mod_Pr)
public, protected sau private, deci o derivare poate să fie publică, protejată sau privată,
accesul rezultat fiind redat în următoarele tabele.
d\b#+
Accesul în clasa de bazăMod_PrAccesul în clasa
derivatăprivate*Privateprivateprotected sau
publicProtectedprotectedPublicneschimbat (protected sau public) +#+###
26.11.18 105
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Deoarece relaţia de derivare este poate cea mai importantă relaţie dintre clase, sunt
oferite facilităţi de implementare, care permit următoarele facilităţi:
economia de cod – reutilizarea codului scris o singură dată după care se moşteneşte,
Relaţiile de derivare (de fapt şi celelalte relaţii dintre clase) sunt stabilite la
compilare, deci nu se mai pot modifica pe parcursul execuţiei. Mai trebuie cunoscut faptul
că prin derivare nu se pot moşteni constructorii, destructorii, elementele prietene (funcţii,
clase sau metode friend) şi nici operatorii redefiniţi.
Exemplu:
// Relatia de derivare \\
#include <conio.h>
#include <string.h>
#include <iostream.h>
class N {
protected: char* c;
public: N (char* s) { c=new char[strlen(s)+1]; strcpy(c,s); }
~N ( ) { delete [ ] c; }
char* Modul ( ) { return c; }
};
class Z : public N
{
private: char Semn;
public: Z (char* s) : N(s+1) { Semn=s[0]; }
~Z ( ) { }
char Semnul( ) { return Semn; }
};
26.11.18 106
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Conversia unui obiect dintr-o clasă derivată într-un obiect aparţinând clasei de bază
este permisă, invers însă nu (sursa trebuie să acopere destinaţia):
Contra_Exemplu:
// Conversii la derivare ? \\
…
void main (void)
{ clrscr();
N n("1234"); Print (n);
Z k(n); Print (k); Error CONVCDCB.CPP 28: Could not find a match for 'Z::Z(N)'
N* i = new N(k); Print (*i);
Z* j = new Z(i); Print (*j); Error CONVCDCB.CPP 30: Could not find a match for 'Z::Z(N *)'
} getche();
Pentru o funcţie care are ca parametru formal un obiect al clasei de bază este permis
apelul având ca parametru un obiect al clasei derivate, invers nu (o funcţie care are ca
parametru formal un obiect al clasei derivate, nu poate fi apelată având ca parametru actual
un obiect al clasei de bază).
Exemplu:
// Conversie la derivare \\
#include <conio.h>
#include <string.h>
#include <iostream.h>
class N {
protected: char* c;
public: N ( ) { c=new char[2]; c[0]='0'; c[1]=0; }
N (char* s) { c=new char[strlen(s)+1]; strcpy(c,s); }
N (N& n) { c=new char[strlen(n.c)+1]; strcpy(c,n.c); }
~N ( ) { delete [ ] c; }
char* Modul ( ) { return c; }
};
void Print (N n) { cout << n.Modul() << endl; }
class Z : public N
{
private: char Semn;
public: Z( ) : N( ) { Semn='+' ; }
Z (char* s) : N(s+1) { Semn=s[0]; }
~Z ( ) { }
char Semnul( ) { return Semn; }
};
void Print (Z n) { cout << n.Semnul() << n.Modul() << endl; }
void WriteAbs (N n) { Print( n); }
void WriteAbs_(N*n) { Print(*n); }
void main (void)
{ clrscr();
Z k("+123"); Print (k);
N n(k); Print (n);
WriteAbs(n);
WriteAbs(k);
Z* p=new Z("-456"); Print (*p);
N* q; q = p; Print (*q);
WriteAbs(*p); WriteAbs_(p);
WriteAbs(*q); WriteAbs_(q); getche();
}
26.11.18 107
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Relaţia de derivare \\
#include <conio.h>
#include <iostream.h>
#include "Vect_Der.h"
void main (void)
{ int n; clrscr();
cout << " Dati n : "; cin >> n;
Vect_Der X(n); X.Print();
int a,p;
do { cout << " Dati a : "; cin >> a;
if (p=X.CautSec(a)) cout << " Pe poz." << p << endl;
else if(a) cout << " Inexistent! " << endl; }
while (a);
cout << " Dati m : "; cin >> n;
Vect_Der* Y=new Vect_Der(n); Y->Sort(); Y->Print();
do { cout << " Dati b : "; cin >> a;
if (p=Y->CautBin(a)) cout << " Pe poz." << p << endl;
else if(a) cout << " Inexistent! " << endl; }
while (a); getche();
}
26.11.18 108
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Clasă Derivată \\ << Vect_Der.h >>
#include "VectBaza.h"
class Vect_Der : public VectBaza {
public: Vect_Der (int=10);
int CautSec (int);
int CautBin (int);
};
În exemplul care urmează, datele x,y (din clasa de bază Punct) au fost declarate
protected deoarece clasa derivată (Cerc) le referă. La clasa derivată am utilizat
modificatorul public pentru a putea utiliza şi pentru Cerc operaţia Contine (PC).
// Program Fct_NeVirtuala; \\
#include <stdio.h>; #include <conio.h>; #include <iostream.h>; #include <math.h>;
float Sqr (float x) { return x*x; }
class Punct {
protected:
float x,y;
public:
Punct (float x0=0, float y0=0);
float Dist (Punct P);
int Contine(Punct P);
};
Punct::Punct (float x0, float y0) { x=x0; y=y0; }
float Punct::Dist (Punct P) {return sqrt(Sqr(x-P.x)+Sqr(y-P.y)); }
int Punct::Contine(Punct P) {return Dist(P)==0; }
class Cerc : public Punct
{ float r;
public:
Cerc (float x0=0, float y0=0, float raza=0)
{x=x0; y=y0; r=raza;}
float Dist (Punct P)
{Punct C(x,y); return C.Dist(P)-r; }
};
void main (void)
{ Punct P(3,4); Cerc C(0,0,5);
if (C.Contine(P)) cout << " Cercul C contine punctul P." << endl;
else cout << " Cercul C nu contine punctul P." << endl; getch();
} // R e z u l t a t e :
Cercul C nu contine punctul P.
Se observă în exemplul de mai sus că rezultatul nu este cel dorit. Acest neajuns îl
vom rezolva mai târziu declarând Distanţa ca funcţie virtuală (pentru legare dinamică).
26.11.18 109
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Faţă de moştenirea simplă, în care dintr-
Cb Cb1 Cb2
o singură clasă de bază se derivează una sau
mai multe clase derivate (specializate),
moştenirea multiplă presupune existenţa mai Cd1 Cd2 Cd
multor clase de bază din care un sau mai multe
clase moştenesc diverse caracteristici. Moştenire simplă Moştenire multiplă
Declararea unei clase derivate din mai multe clase de bază se face astfel:
class Clasă_de_bază_1 { … };
class Clasă_de_bază_2 { … };
class Clasă__derivată : Mod_Pr Clasă_de_bază_1, Mod_Pr Clasă_de_bază_2
{ … };
Cl_Der1 Cl_Der2
Clasă_Derivată
26.11.18 110
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Dacă dorim realizarea unei singure copii a atributelor moştenite, vom folosi
moştenirea multiplă virtuală:
Cl_Bază
Cl_Der1 Cl_Der2
Clasă_Derivată
26.11.18 111
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Aşa cum se poate vedea în exemplul următor, vom avea un nume de mamifer şi un
nume domestic.
// P ro g r a m C l a s e N e Vi r t u a l e ; \\
#include <iostream.h>
#include <conio.h>
#include <string.h>
class Animal { protected: char* Nume;
public: Animal (char *nume) { strcpy(Nume,nume); }
};
class Mamifer : public Animal {
protected: int Greu;
public: Mamifer (char* nume,int gr) : Animal(nume) { Greu=gr;}
};
class Domestic: public Animal {
protected: int Pret;
public: Domestic(char* nume,int pr) : Animal(nume) { Pret=pr;}
};
class Caine : public Mamifer, public Domestic {
protected: int Lant;
public: Caine(char* numeM,char* numeD, int gr, int pr, int l) :
Mamifer(numeM,gr), Domestic(numeD,pr) { Lant=l;}
void Tip() { cout << " Nume Mamifer : " << Mamifer::Nume << endl
<< " Nume Domestic: " << Domestic::Nume << endl
<< " Greutate : " << Greu << endl
<< " Pret : " << Pret << endl
<< " Lant : " << Lant << endl ;}
};
void main (void)
{ clrscr();
Caine c ("Cane","Nero",13,1300,8); c.Tip();
getch();
} // Rezultate:
Nume Mamifer : Cane
Nume Domestic: Nero
Greutate : 13
Pret : 1300
Lant : 8
26.11.18 112
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Dacă dorim ca datele membru să fie prezente într-un singur exemplar în clasele
derivate, atunci vom utiliza clase virtuale. O clasă de bază devine virtuală prin moştenire
dacă se declară aceasta prin cuvântul virtual plasat înaintea clasei (devenind astfel clasă
virtuală faţă de clasa derivată).
Programul anterior modificat astfel încât numele să fie memorat într-un singur
exemplar este următorul:
// P ro g r a m C l a s e Vi r t u a l e ; \\
#include <iostream.h>
#include <conio.h>
#include <string.h>
class Animal { protected: char* Nume;
public: Animal (char* nume) { strcpy(Nume,nume); }
};
class Mamifer : virtual public Animal { // Animal este clasă virtuală pentru Mamifer
protected: int Greu;
public: Mamifer (char* nume,int gr) : Animal(nume) { Greu=gr;}
};
class Domestic: virtual public Animal { // Animal este clasă virtuală pentru Domestic
protected: int Pret;
public: Domestic(char* nume,int pr) : Animal(nume) { Pret=pr;}
};
class Caine : public Mamifer, public Domestic {
protected: int Lant;
public: Caine(char* nume, int gr, int pr, int l) :
Animal(nume), Mamifer(nume,gr), Domestic(nume,pr) {Lant=l;}
void Tip() { cout << " Nume Animal : " << Nume << endl
<< " Greutate : " << Greu << endl
<< " Pret : " << Pret << endl
<< " Lant : " << Lant << endl ;}
};
void main (void)
{ clrscr();
Caine c ("Lup",13,1300,8); c.Tip();
getch();
} // Rezultate:
Nume Animal : Lup
Greutate : 13
Pret : 1300
Lant : 8
26.11.18 113
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Pentru o ierarhie ca cea din figura alăturată,
în care avem clase virtuale () şi nevirtuale (), se A
execută mai întâi constructorii claselor de bază
virtuale apoi cei ai claselor nevirtuale, iar
constructorul clasei de bază se va executa pentru o B C D E F
singură dată toate exemplarele virtuale şi câte o dată
pentru fiecare exemplar nevirtual.
G
Exemplul:
// P ro g r a m I e r a r h i e C l a s e Vi r t u a l e / N e v i r t u a l e ; \\
#include <iostream.h>
#include <conio.h>
class A { public: A (char* a) { cout << " A : " << a << endl; }
class B: virtual public A {
public: B (char* b) : A(b) { cout << " B : " << b << endl; }
class C: virtual public A {
public: C (char* c) : A(c) { cout << " C : " << c << endl; }
class D: public A {
public: D (char* d) : A(d) { cout << " D : " << d << endl; }
class E { public: E (char* e) { cout << " E : " << e << endl; }
class F { public: F (char* f) { cout << " F : " << f << endl; }
class G: public B, public C, public D, public E, virtual public F {
public: G (char* g) : A(g), B(g), C(g), D(g), E(g), F(g)
{ cout << " G : " << g << endl; }
void main (void)
{ clrscr();
G Ob("Ob."); getch();
} // Rezultate:
A : Ob.
F : Ob.
B : Ob.
C : Ob.
A : Ob.
D : Ob.
E : Ob.
G : Ob.
26.11.18 114
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
26. Polimorfism
Două obiecte sunt compatibile dacă aparţin aceleaşi clase (evident) dar şi două
variabile
a) de tip pointer la clasa de bază, respectiv pointer la clasa derivată,
b) de tip referinţă (pointer constant) la clasa de bază, respectiv referinţă la clasa derivată .
Legarea unei metode (binding), înţelegând prin aceasta cenexiunea logică dintre o
entitate şi o proprietate a acesteia (corespondenţa dintre un mesaj trimis unui obiect, adică
ordinul de apel, şi metoda care se execută ca răspuns la acesta) poate fi:
Timpurie (statică – early-binding) – compilatorul şi editorul de legături vor fixa adresa
metodei care se execută, fără ca aceasta să mai
poată fi modificată pe parcursul execuţiei;
Târzie (dinamică – late-binding) – compilatorul va construi un tablou de adrese ale
metodelor posibile de apel, iar determinarea
adresei metodei dorite se va efectua doar la
execuţie. În funcţie valoarea pointerului spre
clasa de bază, care poate conţine şi adresa unui
obiect al clasei derivate, se va alege metoda
corespunzătoare.
26.11.18 115
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
26.1. Funcţii membru Vi rt u al e
Implicit, o metodă este legată static (early, la compilare), iar dacă se doreşte o
legare dinamică (late, la execuţie) se va declara virtuală prin scrierea cuvântului virtual
înaintea metodei. O metodă virtuală a unei clase de bază, poate fi moştenită într-o clasă
derivată sau poate fi redefinită (înlocuită - overriding). O metodă se declară vituală în
clasa de bază (nu se poate declara virtuală doar într-o clasă derivată.
Se poate observa în exemplul următor că dacă dorim ca rezultatul să fie
“Baza/Derivata” şi la apelul funcţiei g, trebuie să declarăm funcţia f virtuală, altfel
rezultatul ar fi “Baza/Baza”.
// Met od ă vi r t u al ă \\
# include <conio.h>
# include <iostream.h>
class Cb { public:
virtual void f() { cout << " Baza " << endl; }
};
class Cd : public Cb
{ public: void f() { cout << " Derivata " << endl; }
};
void g(Cb* p) { p->f(); }
void main ()
{ clrscr();
Cb* Pb = new Cb; Cd* Pd = new Cd;
Pb->f(); Pd->f(); // Legare Statica
g(Pb); g(Pd); // Legare Dinamica
delete Pb; delete Pd;
getche();
}
În exemplul următor vom utiliza variabile de tip referinţă la clasa de bază, respectiv
la clasa derivată.
// Met od ă vi r t u al ă \\
# include <conio.h>
# include <iostream.h>
class Cb { public:
virtual void f() { cout << " Baza " << endl; }
};
class Cd : public Cb
{ public: void f() { cout << " Derivata " << endl; }
};
void g(Cb& r) { r.f(); }
void main ()
{ clrscr();
Cb Ob; Cd Od;
Ob.f(); Od.f(); // Legare Statica
g(Ob); g(Od); // Legare Dinamica
getche();
}
26.11.18 116
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În următorul exemplu se poate deduce necesitatea legării dinamice, pentru a putea
calcula corect distanţa de la un punct la un cerc şi respectiv la un segment (la o dreaptă).
Din păcate pentru că metoda Contine există în dublu exemplar (Stanga şi Dreapta) apelul
nu se poate efectua cum ar fi de dorit!
// Met od ă vi r t u al ă \\
#include <conio.h>;
#include <iostream.h>;
#include <math.h>;
float Sqr (float x) { return x*x; }
class Punct { protected: float x,y;
public: Punct (float x0, float y0) { x=x0; y=y0; }
Punct (Punct &P) { x=P.x; y=P.y; }
virtual float Dist (Punct P) {return sqrt(Sqr(x-P.x)+Sqr(y-P.y));
int Contine(Punct P) {return Dist(P)==0; };
};
class Cerc : public Punct { float r;
public: Cerc (float x0, float y0, float R):Punct(x0,y0){r=R;}
float Dist (Punct P) {Punct C(x,y); return C.Dist(P)-r; }
};
26.11.18 117
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Aproape orice metodă poate fi virtuală, chiar şi metodele inline, metodele friend
(dar nu şi funcţiile friend) operatorii (dacă nu se redefinesc prin funcţii friend) şi
destructorii, în schimb constructorii şi metodele statice nu pot fi virtuale.
În exemplul prezentat în continuare, al doilea produs ( 2/3 * 4/5 = 8/15) nu va fi
afişat dacă operatorul de înmulţire a două numere raţionale nu este declarat virtual,
(deoarece operatorul *= va apela operatorul de înmulţire pentru Q în loc de F cum ar
trebui, a şi b fiind din clasa F). Se observă că la înmulţirea a două obiecte din clasa Q nu
sunt tipărite fracţiile care se înmulţesc, pe când la înmulţirea a două obiecte din clasa F
fracţiile care se înmulţesc sunt tipărite.
26.11.18 118
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
26.2. Clase abstracte - funcţii membru virtuale p u r e
O clasă este abstractă dacă ea conţine cel puţin o funcţie membru virtuală pură. O
funcţie membru virtuală este pură dacă ea este declarată (virtual antet = 0) dar nu este
definită în clasa din care face parte ci într-o clasă derivată. Deoarece clasele abstracte
conţin funcţii membru nedefinite (virtuale pure), nu se pot crea obiecte aparţinând acestora
(nu pot fi instanţiate, dar se pot defini variabile de tip pointer sau referinţă la o clasă
abstractă), iar dacă funcţiile virtuale nu sunt definite nici în clasele derivate, atunci şi aceste
clase devin abstracte (o clasă derivată dintr-o clasă abstractă rămâne abstractă dacă nu s-au
redefinit toate metodele pure moştenite, iar în caz contrar devine clasă concretă).
26.11.18 119
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În exemplul următor vom da trei caracterizări pentru un anumit animal în funcţie de
greutatea lui şi cea medie (slab/gras), vârsta lui şi cea medie (tânăr/bătrân), şi viteza lui (de
deplasare) şi cea medie (lent/rapid), acestea pentru un Porumbel, Urs sau Cal.
/ / Cl as e A bs tr ac te - M et od e Pure \ \
#include <iostream.h>
#include <conio.h>
class Animal { protected: double Greut, Varsta, Viteza;
public: Animal (double Kg, double Ani, double Km_H)
{Greut= Kg; Varsta=Ani, Viteza=Km_H;}
virtual double Greut__Medie () = 0;
virtual double Varsta_Medie () = 0;
virtual double Viteza_Medie () = 0;
int Slab () { return Greut < Greut__Medie(); }
int Tanar() { return Varsta< Varsta_Medie()/2; }
int Lent () { return Viteza< Viteza_Medie(); }
void Tip () { cout << ( Slab ()? "slab, " : "gras, " )
<< ( Tanar()? "tanar, " : "batran," )
<< ( Lent ()? "lent \n" : "rapid\n" );}
};
class Porumbel:public Animal {
public: Porumbel (double Kg, double Ani, double Km_H) :
Animal(Kg, Ani, Km_H) { }
double Greut__Medie () { return 0.5; }
double Varsta_Medie () { return 6.0; }
double Viteza_Medie () { return 90.0; }
};
class Urs: public Animal {
public: Urs (double Kg, double Ani, double Km_H) :
Animal(Kg, Ani, Km_H) { }
double Greut__Medie () { return 450; }
double Varsta_Medie () { return 43; }
double Viteza_Medie () { return 40; }
};
class Cal: public Animal {
public: Cal (double Kg, double Ani, double Km_H) :
Animal(Kg, Ani, Km_H) { }
double Greut__Medie () { return 1000; }
double Varsta_Medie () { return 36; }
double Viteza_Medie () { return 60; }
};
void main (void)
{ clrscr();
Porumbel p (0.6, 1, 80); p.Tip();
Urs u (500,40, 46); u.Tip();
Cal c (900, 8, 70); c.Tip(); getch();
} // Rezultate:
gras, tanar, lent
gras, batran, rapid
slab, tanar, rapid
26.11.18 120
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În exemplul următor vom apela o funcţie Draw pentru a Figură
desena o figură oarecare (Punct, Pătrat sau Cerc) şi o funcţie Arie
care va aplica formula caracteristică fiecărei figuri geometrice: Punct Pătrat Cerc
/ / Cl as ă A bs tr ac tă - M et od e Pure \ \
# include <Conio.h>
# include <Process.h>
# include <Iostream.h>
# include <Graphics.h>
class Figura { protected: int x,y;
public: Figura (int u=0, int v=0) { x=u; y=v; }
virtual void Draw () = 0; // Pura sau Nula
{ }
virtual int Arie () = 0;
int Pret () { return Arie()*100+1; }
};
class Punct : public Figura {
int Cul;
public: Punct (int u, int v, int
c=WHITE):Figura(u,v)
{ Cul=c;
}
void Draw() { putpixel(x,y,Cul); }
int Arie() { return 0; }
};
class Patrat : public Figura {
int Lat;
public: Patrat (int u, int v, int L=1) :
Figura(u,v)
{ Lat=L;
}
void Draw() { moveto(x,y);
linerel(0,+Lat); linerel(+Lat,0);
linerel(0,-Lat); linerel(-
Lat,0); }
int Arie() { return Lat*Lat; }
};
class Cerc : public Figura {
int Raza;
public: Cerc (int u, int v, int R=1) : Figura(u,v)
{ Raza=R;}
void Draw() { circle(x,y,Raza); }
int Arie() { return 3*Raza*Raza; }
};
void InitGraf(void) { int Gd = DETECT, Gm; initgraph(&Gd, &Gm, "C:\\BorlandC\\Bgi"); }
void main (void)
{ clrscr();
Figura* Fig[22];
int i,n; cout << " Dati n : "; cin >> n;
for (i=0; i<n; i++) { int t,x,y,z;
cout << " Dati fig." << i+1 << "(t,x,y,z): "; cin >> t >> x >> y >>
z;
switch (t) { case 1: Fig[i]=new Punct (x,y,z); break;
case 2: Fig[i]=new Patrat(x,y,z); break;
case 3: Fig[i]=new Cerc (x,y,z); break;
default: exit(1);
};
cout << " Pret = " << Fig[i]->Pret() << endl;
26.11.18 121
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
};
getche(); InitGraf();
for (i=0; i<n; i++) { setcolor(15-i); Fig[i]->Draw();}
getche(); closegraph();
}
26.11.18 122
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
27. I e r a r h i i p e n t r u I n t r ă r i / I e ş i r i
Pentru că nu există instrucţiuni de intrare/ieşire, s-au definit funcţii (în C), respectiv
două ierarhii de clase (în C++). Aceste două ierarhii (reprezentate în figurile de mai jos şi
declarate în fişierul iostream.h) realizează operaţiile de intrare/ieşire prin stream-uri (flux de
date sursădestinaţie).
strembuf
filebuf strstreambuf
26.11.18 123
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Pentru tipurile abstracte programatorul poate supraîncărca acest operator, aşa cum
se poate vedea în cele ce urmează.
Pentru a putea tipări un obiect
cout << Obiect ;
vom supraîncărcărca (într-o primă variantă) operatorul de inserare (<<) printr-o funcţie
prieten astfel:
class Clasă { ...
friend ostream& operator << ( ostream&, Clasă );
...
};
Exemplu:
// Progr am O per at or < < Fr ien d; \\
#include <iostream.h> #include <conio.h>
26.11.18 124
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Pentru exemplul anterior (Q) programul va fi următorul:
// Progr am O per a tor << \\
#include <iostream.h>
#include <conio.h>
class Q { protected: int p,q;
public: Q (int m=0, int n=1) { p=m;q=n; }
ostream& Tip (ostream& s)
{ s << p << "/" << q; return s; }
};
ostream& operator << ( ostream& s, Q r ) { return r.Tip(s); }
void main (void)
{ Q r(12,13); clrscr();
cout << " r = " << r << endl; getch();
} // Rezultate:
r = 12/13
Pentru tipurile abstracte programatorul poate supraîncărca acest operator, aşa cum
se poate vedea în cele ce urmează. Pentru a putea citi un obiect
vom supraîncărcărca (într-o primă variantă) operatorul de extragere (>>) printr-o funcţie
prieten astfel:
26.11.18 125
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemplu:
// Progr am O per at or > > Fr ien d; \\
#include <iostream.h>
#include <conio.h>
class Q { protected: int p,q;
public: Q (int m=0, int n=1) { p=m; q=n; }
friend ostream& operator << ( ostream& s, Q r )
{ s << r.p << " / " << r.q; return s; }
friend istream& operator >> ( istream& s, Q& r )
{ s >> r.p >> r.q; return s; }
};
void main (void)
{ Q r; clrscr();
cin >> r;
cout << " r = " << r << endl; getch();
}
26.11.18 126
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
27.3. Intrări/Ieşiri cu format
Atributul x_flags are o valoare implicită pentru fiecare tip standard, care se poate
modifica utilizând funcţia membru setf descrisă în continuare.
Metoda setf are următoarele două forme:
1) long setf (long format);
2) long setf (long bit, long grup);
Funcţia modifică atributul x_flags precizând întraga valoare (varianta a)) sau
precizând un grup de biţi şi bitul dorit din cadrul grupului (varianta b)). Grupele (şi valorile
corespunzătoare) sunt adjustfield (left, right, internal), basefield (dec, oct, hex) şi
floatfield (scientific, fixed) În ambele variante funcţia returnează valoarea anterioară a
atributului x_flags. Referirea grupului şi bitului dorit se face prin numele clasei urmat de
operatorul de rezoluţie şi bitul dorit (ios::b). Valoarea atributului x_flags se poate obţine şi
prin apelul metodei flags (cout.flags() ).
26.11.18 127
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Atributul x_width conţine lungimea minimă a câmpului de afişare a unei date
(respectiv lungimea maximă a câmpului din care se face citirea), având valoarea implicită
nulă (afişare pe lungimea minimă necesară), care se poate modifica utilizând funcţia membru
width descrisă în continuare în ambele forme:
a) int width ( );
b) int width (int lungime);
Funcţia returnează valoarea atributului x_flags (varianta a)) sau modifică atributul
x_width precizând noua valoare (lungime care poate fi o expresie) şi returnează valoarea
anterioară a atributului x_width (varianta b)). După fiecare transfer valoarea atributului
x_flags devine nulă.
Funcţia returnează valoarea atributului x_ fill (varianta a)) sau modifică atributul x_
fill precizând noul caracter de umplere (car) şi returnează valoarea anterioară (varianta b)).
26.11.18 128
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
void main (void)
{ clrscr();
N n;
cout << " Dati un numar natural : "; cin >> n;
cout << " Numarul natural n este: " << n << endl;
cout.setf(ios::hex,ios::basefield);
cout << " Numarul natural n este: " << n << endl;
cout.setf(ios::showbase);
cout << " Numarul natural n este: " << n << endl;
cout << " Numarul natural n este: ";
cout.setf(ios::dec,ios::basefield);
cout.width(6); cout.fill('.');
cout << n << endl;
double x(n); cout << " Numarul n/3.14159 este: ";
cout.setf(ios::fixed,ios::floatfield);
cout.width(9); cout.fill('_'); cout.precision(2);
cout << x/3.14159 << endl;
getche();
}
Rezultate:
Dati un numar natural : 100
Numarul natural n este: 100
Numarul natural n este: 64
Numarul natural n este: 0x64
Numarul natural n este: ...100
Numarul n/3.14159 este: ____31.83
27.3.2. Manipulatori
Atributele x_flags, x_width, x_fill şi x_precision pot fi modificate şi cu ajutorul
manipulatorilor, aceştia având avantajul că pot fi apelaţi înlănţuit (deoarece returnează
referinţă la stream). Primii şapte manipulatori prezentaţi în continuare sunt declaraţi în
fişierul iostream.h, iar ultimii şase în fişierul iomanip.h :
1. ws setarea bitului de salt (skipws)
2. dec conversie în zecimal
3. oct conversie în octal
4. hex conversie în hexa
5. flush vidarea zonei tampon a ob. stream
6. ends inserare car. Nul ‘\0’
7. endl trece la rând nou şi vidarea zonei tampon
1. setbase (int b) defineşte baza în care se face conversia
2. setiosflags (int f) setarea unor biţi precizaţi
3. resetiosflags (long f) ştergerea unor biţi precizaţi
4. setw (int l) defineşte lungimea câmpului
5. setfill (int c) defineşte caracterul de umplere
6. setprecision (int p) defineşte numărul de zecimale
26.11.18 129
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Op erat oru l d e i n serare << cu manipul atori \\
#include <conio.h>
#include <iostream.h>
#include <iomanip.h> Rezultate :
n : 100
class N { int c; n = 100
public: N (int x=0 ) { c=x; }
istream& Cit (istream& s) { s >> c; return s; } n = 64 : 2001
ostream& Tip (ostream& s) { s << c; return s; } n = 0x64
operator double ( ) { return this-> c; } n = ...100
}; n/3= ____33.33
istream& operator >> (istream& s, N& C) { return C.Cit(s); }
ostream& operator << (ostream& s, N C) { return C.Tip(s); }
26.11.18 130
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
27.4. Tratarea erorilor la operaţiile de intrare/ieşire
Dacă o operaţie de intrare/ieşire nu s-a încheiat cu succes (nu s-a desfăşurat corect,
situaţie în care vom spune că streamul ajunge într-o stare de eroare), programul poate lua o
decizie (controlând în acest fel desfăşurarea transferurilor de date în scopul corectitudinii
desfăşurării lor). Tipul erorii (un codul de retur) poate fi aflat verificând biţii datei membru
state (de tip int) prin tipul enumerare io_state definit în clasa ios astfel:
class ios { public: …
enum {
goodbit = 0x00, // operaţie corectă
eofbit = 0x01, // sfârşit de fişier
failbit = 0x02, // eroare intrare/ieşire
badbit = 0x04, // operaţie invalidă
hardfail = 0x80, // eroare fatală
};
…
};
26.11.18 131
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În exemplul următor se repetă citirea până când numărul tastat este corect:
// C on t rol u l erori l or l a op . I/E \\
#include <conio.h>
#include <iostream.h>
class N { int c; Rezultate :
public: N ( ) { c=0; } n : a
istream& Cit (istream& s) { s >> c; return s; } State : 2
ostream& Tip (ostream& s) { s << c; return s; } n : ^Z
}; State : 3
istream& operator >> (istream& s, N& C) { return C.Cit(s); } n : 123
ostream& operator << (ostream& s, N C) { return C.Tip(s); } State : 0
void main (void) n = 123
{
clrscr();
N n; int Gresit;
do {
cout << " n : "; cin >> n ;
cout << " State : " << hex << cin.rdstate() << endl;
if (cin.good()) Gresit=0; else {
Gresit=1;
cin.clear(); // anulare biti
char t[255]; // zona tampon
cin.getline(t,255); // vidare z.t.
} }
while (Gresit);
cout << " n = " << dec << n << endl;
getche();
}
Verificarea stării de eroare a unui stream se mai poate face prin operatorul ! sau prin
conversia într-un pointer fără tip (void*) :
a) operatorul ! este supraîncărcat cu metoda clasei ios:
int operator ! ( ); // returnează o valoare egală cu a funcţiei fail();
De exemplu, în programul Propoziţie.Cpp prezentat anterior instrucţiunea
if (cin.good()) cout << '=' << n << endl;
se poate înlocui cu
if (!!cin) cout << '=' << n << endl;
sau mai simplu cu
if (cin) cout << '=' << n << endl;
b) conversia spre tipul void* permite verificarea stării de eroare a stream-ului, şi poate fi
utilizată în construcţii de forma
if ( s >> dată) … ;
rezultatul (o referinţă la obiectul stream clasei istream) fiind NULL (0) dacă funcţia fail( )
0.
Citirea caracterelor sau a datelor se poate realiza şi cu funcţia membru get definită
astfel:
a) int get ( ); // extrage un caracter din stream-ul curent,
b) istream& get ([un]signed char* z, int n, char c = ’\n’); // nu extrage caracterul c.
26.11.18 132
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În exemplul următor se poate vedea atât utilizarea conversiei spre tipul void*,
precum şi a funcţiei membru get ( în varianta b)):
// C on t rol u l erori l or l a op . I/E \\
#include <iostream.h>
#include <string.h>
class N { int c;
char*Mes;
char*Mer;
char*Met;
public: N (int c=0, char* mes=" : ",
char* mer=" Err.\n",
char* met=" = ");
istream& Cit (istream& s);
ostream& Tip (ostream& s) {s<<Met<<c; return s;}
};
istream& N::Cit(istream& s)
{
cout << Mes;
while (!(s>>c)) { char t[255];
s.clear(); s.get(t,255);
if (s.get()==EOF) return s;
cout << Mer << Mes;
}
return s;
}
26.11.18 133
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Cuprins
pag.
1. Redactarea programelor C.........................................................................1
1.1. Generalităţi...........................................................................................1
1.2. Structura unui program.........................................................................1
1.3. Funcţii..................................................................................................2
1.4. Elementele limbajului...........................................................................3
2. Variabile...................................................................................................4
2.1. Variabile globale...................................................................................4
2.2. Variabile locale.....................................................................................4
2.3. Variabile de tip registru........................................................................5
2.4. Iniţializarea variabilelor.......................................................................6
3. Expresii.....................................................................................................7
3.1. Operatori..............................................................................................7
4. Operaţii de intrare/ieşire.......................................................................11
4.1. Funcţia Printf....................................................................................11
4.2. Funcţia Scanf.....................................................................................12
4.3. Funcţia PutChar................................................................................13
4.4. Funcţia GetChar................................................................................13
4.5. Funcţia GetChe.................................................................................13
4.6. Funcţia GetCh....................................................................................13
5. Instrucţiuni.............................................................................................14
5.1. Instrucţiunea Vidă..............................................................................14
5.2. Instrucţiunea Expresie.......................................................................14
5.3. Instrucţiunea Compusă......................................................................14
5.4. Instrucţiunea If..................................................................................15
5.5. Instrucţiunea Switch..........................................................................15
5.6. Instrucţiunea While............................................................................16
5.7. Instrucţiunea Do_While.....................................................................16
5.8. Instrucţiunea For...............................................................................17
5.9. Instrucţiunea Break.............................................................................17
5.10. Instrucţiunea Continue.......................................................................17
26.11.18 134
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
5.11. Instrucţiunea GoTo.............................................................................17
5.12. Apelul unei funcţii..............................................................................18
6. Pointeri...................................................................................................20
6.1. Declararea unui Pointer......................................................................20
6.2. Operaţii cu Pointeri............................................................................21
6.3. Alocare dinamică a memoriei.............................................................22
6.4. Pointeri la funcţii.............................................................................23
6.5. Utilizarea parametrilor din linia de comandă.....................................24
6.6. Declararea c o n s t antelor..................................................................24
6.7. S t i v a .................................................................................................25
7. Recursiviate............................................................................................25
8. Tipuri de date.........................................................................................26
8.1. Definirea unui tip de dată (typedef)..................................................26
8.2. Tipul enumerare (enum).....................................................................26
8.3. Definirea unei structuri (struct).........................................................27
8.4. Redefinirea unei date (union).............................................................28
8.5. Câmpuri de biti..................................................................................28
26.11.18 135
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
12. Ecranul în mod text.......................................................................43
13. Ecranul în mod grafic....................................................................44
14. Facilităţi C++.................................................................................47
14.1. Extensii ale limbajului C....................................................................47
14.2. Operatori............................................................................................48
14.3. Structură, uniune şi enumerare...........................................................51
16. T i p A b s t r a c t d e D a t ă ..........................................................59
17. Programare orientată obiect (OOP)............................................63
17.1. Definirea Claselor..............................................................................64
17.2. Constructori şi Destructori..............................................................68
26.11.18 136
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
24. Clase Şablon (Template).................................................................91
24.1. Funcţii Şablon (Template)..................................................................91
24.2. Clase Template...................................................................................92
24.3. Implementarea elementelor Template.................................................93
2 6 . P o l i m o r f i s m .............................................................................113
26.1. Funcţii membru Vi r t u a l e ...............................................................114
26.2. Clase abstracte - funcţii membru virtuale p u re ..............................117
2 7 . I e r a r h i i p e n t r u I n t r ă r i / I e ş i r i .........................................120
27.1. Operatorul de inserare <<..............................................................120
27.2. Operatorul de extragere >>...........................................................122
27.3. Intrări/Ieşiri cu format......................................................................124
27.4. Tratarea erorilor la operaţiile de intrare/ieşire..................................128
Cuprins.....................................................................................................131
Bibliografie...............................................................................................135
26.11.18 137
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Bibliografie
26.11.18 138