![]() |
Índex |
Miguel A. Almarza
Departament d'Informàtica IES Mare de Deu de la Merce |
Assignació d'un objecte |
main() { Punt A; Punt C(3,10,'X'); A=C; A.ImprimeixDades(); } |
Assignació d'un objecte amb assignació dinàmica de memòria. |
#include <iostream.h> #include <alloc.h> #include <string.h> #include <stdlib.h> class String { char * Cadena; int Longitud; public: String(); String(char * Punter); ~String(); void Posa(char * Punter); void ImprimeixDades(); } String::String(char * Punter) { if ((Cadena = new char [strlen(Punter)+1]) == NULL) { cout << "Falta memòria per a aquest string\n"; exit(1); } strcpy(Cadena,Punter); Longitud=strlen(Cadena); } String::String() { Cadena = NULL; Longitud=0; } String::~String() { if (Cadena) delete Cadena; } void String::Posa(char * Punter) { delete Cadena; if ((Cadena = new char [strlen(Punter)+1]) == NULL) { cout << "Falta memòria per a aquest string\n"; exit(1); } strcpy(Cadena,Punter); Longitud=strlen(Cadena); } void String::ImprimeixDades() { cout << "Objecte string.\n"; cout << "Cadena: " << Cadena << "\n"; cout << "Longitud: " << Longitud << "\n"; } main() { String Nom1("Lopez Perez, Pere"); String Nom2("Bru Pi, Pau"); Nom2 = Nom1; } |
Objectes com a paràmetres. |
float Modul(Punt P) { int x,y; x= P.TornaX(); y= P.TornaY(); return sqrt(x*x + y*y); } main() { Punt D(3,4); cout << Modul(D) << '\n'; } |
Objectes com a paràmetres. | |
class String { char * Cadena; int Longitud; public: String(); String(char * Punter); ~String(); void Posa(char * Punter); void ImprimeixDades(); char * TornaPunter(); }; char * String::TornaPunter() { return Cadena; } int ComptaAs(String S) { /*Aquesta funció té una errada greu*/ int i=0; char * Punter; Punter = S.TornaPunter(); while (*Punter) { if (*Punter == 'A') i++; Punter ++; } return i; } main() { String Tira("AlA AlA"); cout << ComptaAs(Tira) << '\n'; } | ![]() |
Devolució d'un punt per una funció. | |
#include <iostream.h> #include <conio.h> class Punt { int x; int y; char Caracter; public: Punt() { x=y=0; Caracter = ' '; }; Punt(int n1,int n2) { x=n1; y=n2; Caracter = ' '; }; Punt(int n1,int n2,char Car) { x=n1; y=n2; Caracter = Car; }; ~Punt(){cout << "Destructor \n";}; void PosaCaracter(char c) {Caracter = c;}; void PosaCoordenades(int n1, int n2) { x = n1; y = n2; }; void Dibuixat() { gotoxy(x,y); cout << Caracter; }; int TornaX() {return x;}; int TornaY() {return y;}; int TornaCaracter(){return Caracter;}; void ImprimeixDades() { cout << "x = " << x; cout << ", y = " << y; cout << ", Caracter = " << Caracter << "\n"; }; }; Punt CanviaXY(Punt Q) { Punt P=Q; int x,y; x = P.TornaX(); y = P.TornaY(); P.PosaCoordenades(y,x); return P; } main () { Punt A(1,5,'A'); Punt B; B = CanviaXY(A); B.ImprimeixDades(); } |
Sortida per pantalla | S'executa: |
Destructor | El destructor pel punt Q de la funció CanviaXY |
Destructor | El destructor pel punt P de la funció CanviaXY |
Destructor | El destructor pel punt provisional després de l'assignació al punt B de la funció main |
x=1,y=5,Caracter=A | B.ImprimeixDades() |
Destructor | El destructor pel punt B de la funció main |
Destructor | El destructor pel punt A de la funció main |
Devolució d'un punt per una funció. | |
/*Aquesta funció té una errada greu*/ String AlReves(String S) { int Lon; char C; char * Punter; Lon= S.TornaLongitud(); Punter = S.TornaPunter(); for(int i=0; i< Lon/2; i++) { C=Punter[i]; Punter[i]=Punter[Lon-i-1];Punter[Lon-i-1]=C; } return S; } main() { String Tira1("ABCDEFG"); String Tira2; Tira2 = AlReves(Tira1); Tira2.ImprimeixDades(); } |
Declaració i inicialització en la mateixa instrucció | Miclasse Ob1 = Ob2; |
Crida a una funció amb un objecte com a paràmetre | ... Funcio(Ob); |
Devolució d'un objecte per part d'una funció | Ob = Funcio(...); |
NomClasse (const NomClasse &Objecte) { Instruccions del constructor. } |
Constructor de còpia per a la classe String. | |
class String { char * Cadena; int Longitud; public: String(){Cadena = NULL;Longitud=0;}; String(char * Punter); String(String &S); ~String(){if (Cadena) delete Cadena;}; void Posa(char * Punter); void ImprimeixDades(); char * TornaPunter(){return Cadena;} int TornaLongitud(){return Longitud;}; }; String::String(String &S) { if ((Cadena = new char [S.TornaLongitud()]) == NULL) { cout << "Falta memòria per a aquest string\n"; exit(1); } strcpy(Cadena,S.TornaPunter()); Longitud=strlen(Cadena); cout << "Executat el constructor de còpia\n"; } |
Veiem que en aquest constructor el que es fa és crear memòria per a un nou objecte on copiarà les dades
rebudes sobre l'objecte S. Per tant no és fa una copia de les dades a nivell de bit com abans i de forma automàtica, sinó que és el programador el que decideix com ha de fer-se la còpia. |
Ús del constructor de còpia per a la declaració d'un objecte String. | |
main() { String Tira1("ABCDEFG"); String Tira2(Tira1); Tira2.ImprimeixDades(); } | La instrucció de declaració de l'objecte Tira2 i inicialització amb les dades de l'objecte Tira1 és Veiem que quan s'executa aquesta instrucció s'executa automàticament el constructor de còpia que hem fet i per tant l'objecte Tira2 té la seva pròpia memòria assignada. No hi ha cap errada. |
![]() |
Ús del constructor de còpia per passar un objecte a una funció. | |
int ComptaAs(String S) { int i=0; char * Punter; Punter = S.TornaPunter(); while (*Punter) { if (*Punter == 'A') i++; Punter ++; } return i; } main() { String Tira("AlA AlA"); cout << ComptaAs(Tira) << '\n'; } | La funció ComptaAs rep com a paràmetre un objecte de la classe String que ha de copiar les seves dades a
l'objecte S. S'executa de forma automàtica el constructor de còpia per a posar aquestes dades a l'objecte S. Així tenim que l'objecte S té la memòria dinàmica assignada diferent de la de l'objecte original i quan acabi l'execució de la funció ComptaAs el destructor de la classe String lliura la memòria de S i no la de l'objecte original. Veiem que a la sortida per pantalla apareix la frase en el moment d'execurtar-se aquest constructor per a l'objecte S. Després apareix el número de lletres A, en aquest cas 4 lletres A. |
![]() |
Ús del constructor de còpia per tornar un objecte una funció. | |
String AlReves(String S) { int Lon; char C; char * Punter; Lon= S.TornaLongitud(); Punter = S.TornaPunter(); for(int i=0; i< Lon/2; i++) { C=Punter[i]; Punter[i]=Punter[Lon-i-1];Punter[Lon-i-1]=C; } return S; } main() { String Tira1("ABCDEFG"); String Tira2; Tira2 = AlReves(Tira1); Tira2.ImprimeixDades(); } | Tenim la funció AlReves que rep un objecte String i que també en torna un altre. Així el constructor de còpia s'executa dues vegades. La primera per crear l'objecte S que rep la funció. La segona vegada que s'executa aquest constructor és per a l'objecte provisional que es crea automàticament per a tornar l'objecte S i que es copiarà a sobre de l'objecte Tira2. Per tant, i com veiem a la sortida per pantalla, apareix dues vegades la frase car la funció constructora ha estat executada dues vegades. |
![]() |
Funcions amigues. | |
#include <iostream.h> #include <math.h> class Complex { float a,b; public: Complex(float x, float y){a=x;b=y} void Imprimeix(){cout << a << " + " << b << "i";} friend int ModulMajor(Complex z1, Complex z2); }; int ModulMajor(Complex z1, Complex z2) { float M1 = sqrt(z1.a*z1.a + z1.b*z1.b); float M2 = sqrt(z2.a*z2.a + z2.b*z2.b); return M1 > M2; } main() { Complex z1(2,5), z2(4,8); z1.Imprimeix(); cout << "\n"; z2.Imprimeix(); cout << "\n"; cout << ModulMajor(z2,z1); } | Declarem una classe Complex que té a i b com a propietats. Hem reduït al mínim possible les funcions membre
amb un constructor i la funció Imprimeix. Després, dins la declaració de la classe Complex, es declara la funció amiga (friend) ModulMajor que segons veiem es defineix fora de la classe com una funció normal. També veiem que tenim accés a les propietats privades dels objectes de la classe Complex, amb instruccions del tipus z1.a. Nota: aquesta funció calcula el mòdul (M1 i M2) dels dos complexos z1 i z2 (Distància del punt (a,b) a l'origen de coordenades). Torna Cert si M2 és major que M1 i fals en cas contrari. |
![]() |
class A { ...... friend tipus B::Func(Paramètres); ...... }; |
#include <iostream.h> class A; //Declaració forward class B { int DatB; public: void PosaDada(int n) {DatB=n;} int TornaSuma(A Obj); }; class A { int DatA; public: void PosaDada(int n){DatA=n;} friend int B::TornaSuma(A Obj); }; int B::TornaSuma(A Obj) { return Obj.DatA + DatB; }; main() { A Obj1; B Obj2; Obj1.PosaDada(25); Obj2.PosaDada(13); cout << "La funció TornaSuma dona: " << Obj2.TornaSuma(Obj1); } |
La funció TornaSuma és una funció membre de la classe B i és amiga de la classe A.
Com que la funció ha de declarar-se dins la classe B hem de posar una declaració forward de la classe A abans. Observem que la funció es declara com amiga dins la classe A. També observem que la instrucció d'aquesta funció fa ús de les dades privades de A. Com veiem a la instrucció ens adonem que la funció és una funció membre de la classe B ja que Obj2 és un objecte d'aquesta classe. |
class VectorEnters { int * Vector; int Longitud; public: VectorEnters(int *Vector, int L); VectorEnters(VectorEnters &Obj); void Imprimeix(); int SumaVector(); float Mitjana(); ~VectorEnters(); }; main() { int V[10] = {1, 3, 5, 7, 9 , 11, 13, 15 , 17, 19} int L = 10; VectorEnters Senars(V,10); VectorEnters C(Senars); cout << C.SumaVector(); } |