AnteriorPosterior

14. Sobrecarga de operadores. Funciones amigas. (2)

  Curso: Introducción a C++, por Nacho Cabanes (antiguo)

14. Sobrecarga de operadores. Funciones amigas. (2)

Una función amiga es aquella que tiene acceso a la parte privada de una clase. Es algo que rompe la encapsulación, por lo que no se debería abusar de ello.

Como ejemplo, vamos a calcular el módulo (la longitud) de un vector. Podemos hacerlo de dos formas. La más correcta (y que no usaremos) sería, dado que el módulo es una propiedad del vector, definirlo como una función miembro del vector, de modo que escribiríamos cosas como "cout << vec1.modulo()". Doy por sentado que eso no supone ninguna dificultad a estas alturas, y vamos a hacerlo de la forma "menos correcta", pero que en este caso será la más didáctica: crearemos una función "módulo" que declararemos como "amiga" para que tenga acceso a la parte privada de nuestro NVector:

  1:  // 
2:
// amiga01.cpp
3:
//
4:
// Introduccion a C++
5:
// Funciones amigas
6:
// Probado con TC++ (MsDos)
7:
//
8:
// Curso de C
9:
// Jose Ignacio Cabanes
10:
//
11:
/////////////////////////////////////////////
12:

13: #include
<iostream.h>
14: #include
<math.h> // Para la raíz cuadrada, sqrt
15:

16:
// ---------------------------------------------------------
17:
// CLASE : NVector
18:
// Vector, determinado por las dos coordenadas de su
19:
// extremo (se supone su origen en el origen de
20:
// coordenadas)
21:
// ---------------------------------------------------------
22:

23:
class NVector {
24:
25:
int coordX, coordY; // Coordenadas del extremo del vector
26:
friend float modulo( NVector v ) // Modulo del vector
27:
{ return sqrt (v.coordX*v.coordX + v.coordY*v.coordY); }
28:
29:
public:
30:
31:
int LeerX(); // Leer valores y fijarlos
32:
int LeerY();
33:
void FijarX( int valor );
34:
void FijarY( int valor );
35:
36:
void Mostrar(); // Mostrar en pantalla: (x,y)
37:
};
38:
39:
// ==========================================================================
40:

41:
//
42:
// A continuación viene el desarrollo de las funciones (métodos)
43:
//
44:
// ========
45:

46:
/* ----------------- NVector ------------------------------- */
47:
/* Leer los valores de las coordenadas */
48:
/* _________________________________________________________ */
49:
50:
int
51: NVector
::LeerX() {
52:
return coordX;
53:
}
54:
55:
int
56: NVector
::LeerY() {
57:
return coordY;
58:
}
59:
60:
61:
/* ----------------- NVector ------------------------------- */
62:
/* Fijar los valores de las coordenadas */
63:
/* _________________________________________________________ */
64:
65:
void
66: NVector
::FijarX( int valor ) {
67: coordX
= valor;
68:
}
69:
70:
void
71: NVector
::FijarY( int valor ) {
72: coordY
= valor;
73:
}
74:
75:
76:
/* ----------------- NVector ------------------------------- */
77:
/* Otras: mostrar */
78:
/* _________________________________________________________ */
79:
80:
void
81: NVector
::Mostrar() {
82: cout
<< "(" << coordX << "," << coordY << ")\n";
83:
}
84:
85:
86:
87:
// ==========================================================================
88:
//
89:
// Finalmente: un programa sencillo de ejemplo
90:
//
91:
// ========
92:

93: NVector vec1
; // Definimos un objeto de la clase "NVector"
94:

95:
main() {
96: vec1.FijarX
(3); vec1.FijarY(2);
97: vec1.Mostrar
();
98:
99: cout
<< "Modulo: " << modulo(vec1) << "\n";
100:
101:
return 0;
102:
}


Creo que no es difícil: a la clase NVector le decimos que tendrá una función amiga, llamada módulo, la cual, de paso, hemos definido allí mismo. En el cuerpo del programa mostramos el valor del módulo de "vec1". La salida de este programa será algo así:

(3,2)
Modulo: 3.06555

Y también podemos decir que una clase será amiga de otra, y por tanto tendrá acceso a toda su parte privada, como ésta que sea capaz de deformar un NVector, haciéndolo más grande o más pequeño, al multiplicar sus componentes por un cierto número:



  1:  // 
2:
// amiga02.cpp
3:
//
4:
// Introduccion a C++
5:
// Clases amigas
6:
// Probado con TC++ (MsDos)
7:
//
8:
// Curso de C
9:
// Jose Ignacio Cabanes
10:
//
11:
/////////////////////////////////////////////
12:

13: #include
<iostream.h>
14: #include
<math.h> // Para la raíz cuadrada, sqrt
15:

16:
// ---------------------------------------------------------
17:
// CLASE : NVector
18:
// Vector, determinado por las dos coordenadas de su
19:
// extremo (se supone su origen en el origen de
20:
// coordenadas)
21:
// ---------------------------------------------------------
22:

23:
class EstiraVector; // La declaramos, para que el compilador
24:
// sepa que existe y que la definiremos más
25:
// tarde
26:

27:
class NVector {
28:
29:
int coordX, coordY; // Coordenadas del extremo del vector
30:
friend class EstiraVector; // Clase amiga
31:

32:
public:
33:
34:
int LeerX(); // Leer valores y fijarlos
35:
int LeerY();
36:
void FijarX( int valor );
37:
void FijarY( int valor );
38:
39:
void Mostrar(); // Mostrar en pantalla: (x,y)
40:
};
41:
42:
43:
class EstiraVector {
44:
45:
public:
46:
47:
void Modifica( NVector &v, int factor ); // Multiplica las componentes
48:
};
49:
50:
51:
// ==========================================================================
52:

53:
//
54:
// A continuación viene el desarrollo de las funciones (métodos)
55:
//
56:
// ========
57:

58:
/* ----------------- NVector ------------------------------- */
59:
/* Leer los valores de las coordenadas */
60:
/* _________________________________________________________ */
61:
62:
int
63: NVector
::LeerX() {
64:
return coordX;
65:
}
66:
67:
int
68: NVector
::LeerY() {
69:
return coordY;
70:
}
71:
72:
73:
/* ----------------- NVector ------------------------------- */
74:
/* Fijar los valores de las coordenadas */
75:
/* _________________________________________________________ */
76:
77:
void
78: NVector
::FijarX( int valor ) {
79: coordX
= valor;
80:
}
81:
82:
void
83: NVector
::FijarY( int valor ) {
84: coordY
= valor;
85:
}
86:
87:
88:
/* ----------------- NVector ------------------------------- */
89:
/* Otras: mostrar */
90:
/* _________________________________________________________ */
91:
92:
void
93: NVector
::Mostrar() {
94: cout
<< "(" << coordX << "," << coordY << ")\n";
95:
}
96:
97:
98:
99:
/* ----------------- EstiraVector -------------------------- */
100:
/* Modifica: multiplica las componentes de un vector por */
101:
/* un cierto factor */
102:
/* _________________________________________________________ */
103:
104:
void
105: EstiraVector
::Modifica( NVector &v, int factor ) {
106: v
.coordX *= factor;
107: v
.coordY *= factor;
108:
}
109:
110:
111:
112:
// ==========================================================================
113:
//
114:
// Finalmente: un programa sencillo de ejemplo
115:
//
116:
// ========
117:

118: NVector vec1
; // Definimos un objeto de la clase "NVector"
119:
EstiraVector e; // Y un "estirador de vectores"
120:

121:
main() {
122: vec1.FijarX
(3); vec1.FijarY(2);
123: vec1.Mostrar
();
124:
125: e
.Modifica(vec1, 3);
126: vec1.Mostrar
();
127:
128:
return 0;
129:
}


Tampoco debería suponer ningún problema: decimos que la clase "EstiraVector" va a ser amiga de "NVector", de modo que tendrá acceso a su parte privada. Eso sí, como no quiero limitarme a leer los datos de la parte privada, sino que deseo modificarlos, el vector a modificar lo paso como referencia (en caso contrario, los cambios no se guardarían al salir de "Modifica").

Por otra parte, la obligación de declarar la clase "EstiraVector" para que el compilador no nos regañe cuande vea que la mencionamos dentro de "NVector" también es algo bastante razonable, que no debería sorprendernos. Más adelante es cuando ya damos los datos concretos sobre cómo debe trabajar esa clase.

Así que sigamos: vamos ahora a ver cómo redefinir el operador <<...




Actualizado el: 13-08-2006 21:16

AnteriorPosterior