funciones amigas - Oldemar Rodríguez Rojas

Transcripción

funciones amigas - Oldemar Rodríguez Rojas
Funciones y Clases
Amigas en C++
Dr. Oldemar Rodríguez Rojas
Escuela de Informática
Universidad de Nacional
INTRODUCCIÓN A LAS
FUNCIONES AMIGAS
Habrá momentos en los que se quiera que una
función tenga acceso a los miembros privados
de una clase sin que esa función sea realmente
un miembro de esa clase.
De cara a esto, C++ soporta las funciones
amigas. Una función amiga no es un miembro
de una clase, pero tiene acceso a sus
elementos privados.
¿Para qué sirven las funciones amigas?
Dos motivos por los que las funciones amigas son útiles
tienen que ver con la sobrecarga de operadores y la
creación de ciertos tipos de funciones de E/S.
Una tercera razón para las funciones amigas es que
habrá momentos en los que una función tenga acceso a
los miembros privados de dos o más clases diferentes.
Este uso es el que se examina aquí. Una función amiga
se define como una función no miembro normal. Sin
embargo, dentro de la declaración de clase para la que
será una función amiga, está también incluido su
prototipo, precedido por la palabra clave friend.
Para entender cómo funciona, examine este breve
programa:
#include <iostream.h>
#include <conio.h>
class myclass {
int n, d;
public:
myclass(int i,int j) {n=i;d=j;}
// declara una función amiga de
myclass
friend int isfactor(myclass ob);
};
int isfactor(myclass ob) {
if(!(ob.n % ob.d))
return 1;
else
return 0;
}
int main() {
myclass ob1(10,2),ob2(13,3);
if(isfactor(ob1))
cout << "2 es un factor de 10\n";
else
cout << "2 no es un factor de
10\n";
if(isfactor(ob2))
cout << "3 es un factor de 13\n";
else
cout << "3 no es un factor de
13\n";
char ch=getch();
return 0;
}
En este ejemplo, myclass declara su función constructora y
la función amiga isfactor() dentro de su declaración de
clase. Debido a que isfactor() es una función amiga de
myclass, isfactor() tiene acceso a sus áreas privadas. Esto
es por lo que dentro de isfactor(), es posible referirse
directamente a ob.n y ob.d.
Es importante entender que una función amiga no es un
miembro de la clase de la que es amiga. Por lo tanto, no es
posible llamar a una función amiga usando un nombre de
objeto y un operador de acceso a miembro de clase (un
punto o flecha).
Por ejemplo, suponiendo el ejemplo
sentencia está mal:
ob1.isfactor(); // ERROR
anterior,
esta
Las funciones amigas se llaman igual que las funciones
normales.
Aunque una función amiga tiene conocimiento de los
elementos privados de la clase de la que es amiga, sólo
puede acceder a ellos a través de un objeto de la clase. Es
decir, a diferencia de un miembro de myclass, que se
pueden referir directamente a n o d, una función amiga
puede acceder a estas variables sólo en conjunción con un
objeto que esté declarado dentro o pasado a la función
amiga.
Debido a que las funciones amigas no son miembros de
una clase, normalmente se le pasarán uno o más objetos
de la clase para la que están definidas.
Una función amiga no es miembro y no se puede calificar
mediante un nombre de objeto. Se tiene que llamar como
una función normal.
Una función amiga no se hereda. Es decir, cuando una
clase base incluye una función amiga, la función amiga no
es una función amiga de la clase derivada.
Otro punto importante sobre las funciones amigas es que
una función amiga puede ser amiga de más de una clase.
Un uso común (y bueno) de una función amiga se da
cuando dos tipos diferentes de clases tienen alguna
cantidad en común que hay que comparar. Por ejemplo,
considere el siguiente programa, que crea una clase
llamada car y una clase llamada truck, cada una
conteniendo, como una variable privada, la velocidad del
vehículo que representa, veamos el siguiente ejemplo:
Esto permite implementar relaciones de Asociación.
#include <iostream.h>
#include <conio.h>
class truck; // una referencia anticipada
class car {
int passengers;
int speed;
public:
car(int p,int s) {passengers=p;speed=s;}
friend int sp_greater(car c, truck t);
};
class truck {
int weight;
int speed;
public:
truck(int w,int s) {weight=w;speed=s;}
friend int sp_greater(car c, truck t);
};
int sp_greater(car c,truck t) {
return c.speed-t.speed;
}
int main() {
int t;
car c1(6,55),c2(2,130);
truck t1(10000,55), t2(20000,72);
cout << "Comparando el y tl:\n";
t=sp_greater(c1,t1);
if(t<0)
cout <<"El camión es más rápido. \n";
else
if(t==0)
cout << "La velocidad del coche y del camión es la misma.\n";
else
cout << "El coche es más rápido.\n";
cout << "\nComparando c2 y t2:\n";
t=sp_greater(c2,t2);
if(t<0)
cout << "El camión es más rápido.\n";
else
if(t==0)
cout << "La velocidad del coche y del camión es la misma.\n";
else
cout << "El coche es más rápido.\n";
char ch=getch(); return 0;
}
Una función puede ser
miembro de una clase y amiga
de otra.
Veamos el siguiente ejemplo:
#include <iostream.h>
#include <conio.h>
class truck; // una referencia anticipada
class car {
int passengers;
int speed;
public:
car(int p,int s) {passengers=p;speed=s;}
int sp_greater(truck t);
};
class truck {
int weight;
int speed;
public:
truck(int w,int s) {weight=w;speed=s;}
friend int car::sp_greater(truck t);
};
int car::sp_greater(truck t) {
return speed - t.speed;
}
int main() {
int t;
car c1(6,55),c2(2,130);
truck t1(10000,55), t2(20000,72);
cout << "Comparando el y tl:\n";
t=c1.sp_greater(t1);
if(t<0)
cout <<"El camión es más rápido. \n";
else
if(t==0)
cout << "La velocidad del coche y del camión es la misma.\n";
else
cout << "El coche es más rápido.\n";
cout << "\nComparando c2 y t2:\n";
t=c2.sp_greater(t2);
if(t<0)
cout << "El camión es más rápido.\n";
else
if(t==0)
cout << "La velocidad del coche y del camión es la misma.\n";
else
cout << "El coche es más rápido.\n";
char ch=getch(); return 0;
}
Clases Amigas
El caso más común de amistad se aplica a clases completas.
El modificador “friend” puede aplicarse a clases o funciones para inhibir
el sistema de protección.
Las relaciones de "amistad" entre clases son parecidas a las amistades
entre personas:
La amistad no puede transferirse, si A es amigo de B, y B es amigo de C, esto no
implica que A sea amigo de C. (La famosa frase: "los amigos de mis amigos son mis
amigos" es falsa en C++, y probablemente también en la vida real).
La amistad no puede heredarse. Si A es amigo de B, y C es una clase derivada de B,
A no es amigo de C. (Los hijos de mis amigos, no tienen por qué ser amigos míos. De
nuevo, el símil es casi perfecto).
La amistad no es simétrica. Si A es amigo de B, B no tiene por qué ser amigo de A.
(En la vida real, una situación como esta hará peligrar la amistad de A con B, pero de
nuevo me temo que en realidad se trata de una situación muy frecuente, y
normalmente A no sabe que B no se considera su amigo).
#include <iostream>
using namespace std;
class Amigable {
private:
int secreto;
friend void FuncionAmiga(Amigable& o);
friend class Amiga;
};
class Amiga {
public:
void mirar(Amigable& o) {
o.secreto = 120;
cout << o.secreto << endl;
}
};
void FuncionAmiga(Amigable& o) {
o.secreto = 121;
cout << o.secreto << endl;
}
// Programa principal
int main() {
Amiga amiga;
Amigable amigable;
amiga.mirar(amigable);
FuncionAmiga(amigable);
system("pause");
system("cls");
return 0;
}
<Ver Ej1.CPP>

Documentos relacionados