Professional Documents
Culture Documents
1. Introducción
9. Sobrecarga de operadores
2. Encapsulamiento
Metodologı́a de la Programación II 9.1 Sobrecarga del operador =
3. Constructores 9.2 Código reutilizable
9.3 Operador []
4. Destructor
9.4 Operadores aritméticos
5. Prioridad de ejecución 9.5 Operadores << y >>
Clases en C++ 6. El constructor de copia 10. Objetos y miembros const
7. Funciones inline 11. Miembros static
8. El puntero this
Clases 2
Las clases permiten la construcción de tipos definidos por el usuario, exten- class MiClase{
diendo el conjunto de tipos elementales. // Declaracion de datos miembro
// Declaracion de metodos
Las clases son una extensión y evolución natural de los struct. };
Cada clase contiene:
MiClase objeto1, objeto2;
datos (los datos miembro o campos) y En la declaración de una clase, para cada dato miembro (campo o método),
debe especificarse mediante los modificadores de acceso el ámbito desde el cual
las funciones que los manipulan (las funciones miembro o los métodos). puede accederse a dicho miembro. Son:
Clases 3 Clases 4
private Ventajas de las clases
Sólo se permite su acceso desde las funciones miembro (métodos) de la
clase. Ocultación de la información. Permite:
public • Que los usuarios no puedan hacer mal uso de los datos propios de un objeto,
proporcionando la integridad de los datos, por tanto promoviendo un
Se permite su acceso desde cualquier punto que pueda usar la clase. Un
software más robusto.
dato público es accesible desde cualquier objeto de la clase.
• Separación efectiva representación-implementación. Ocultar la imple-
protected mentación de las funciones, propiciando disponer de los derechos propios en
Se permite su uso en los métodos de la clase y en los de las clases la elaboración de software, y lo que es más importante, poder modificar la
derivadas mediante herencia. implementación sin que afecte al usuario.
Clases 5 Clases 6
class Polinomio {
private: Como cualquier función en C++.
float * Coef;
int Grado; Se trata de especificar los prototipos de los métodos de la clase. En algunos
int MaxGrado; casos, incluso su definición (funciones inline).
Clases 7 Clases 8
Toda clase dispone, por defecto, de un constructor, de un destructor y del
int LeeGrado (void) const; operador de asignación:
float LeeCoeficiente (int i) const;
float Evalua (float x) const; #include <string>
void PintaPolinomio (const char * const msg) const; #include <iostream>
} #include <iomanip>
using namespace std;
Un método const impide la modificación de los datos miembro del objeto al
que se aplican. // Una clase minimalista
class Test {};
Es usual disponer de funciones miembro públicas que modifican y/o leen el Test global;
valor de los datos privados.
void funcion (void){
Pueden definirse funciones privadas que pueden ser de utilidad (funciones cout << "Ejecutando: funcion\n";
auxiliares) para las funciones públicas. Test local_f;
“Métodos especiales”: Constructores y destructor. cout << "Saliendo de: funcion\n";
}
Clases 9 Clases 10
Clases 11 Clases 12
Es habitual que las clases ofrezcan un conjunto de funciones públicas a través de
las cuales se puede actuar sobre los datos miembro, que serán privados. 3.3 Constructores
Estas funciones forman la interfaz de la clase. Cuando se crea un objeto de una clase siempre se llama automáticamente a
un constructor.
Polinomio pol1;
Polinomio * pol2 = new (nothrow) Polinomio;
Clases 13 Clases 14
En cualquier caso:
Pueden haber varios constructores para una clase. Es un buen ejemplo de
sobrecarga. Siempre deberı́a implementarse, al menos, el constructor básico (sin paráme-
tros), el constructor por defecto, de manera que el programador pueda
Un constructor tiene el mismo nombre que la clase en la que está declarado y controlar y personalizar la creación e iniciación.
no devuelve nada.
CUIDADO: no es una función void.
Importante:
¿Qué ocurre si en una clase no se define ningún constructor? El compilador sólo crea un constructor de oficio si no se ha definido ningún
constructor.
El compilador crea un constructor de oficio, sin argumentos, que inicia los
datos miembros a cero.
Clases 15 Clases 16
#include <string>
Test :: Test (string cad){
#include <iostream>
msg = cad;
#include <iomanip>
cout << " Constructor 2 de Test " << "--> " << msg << "\n";
using namespace std;
}
Test global ("global"); // Objeto global
class Test{
private:
void funcion (void){
string msg;
cout << "Ejecutando : funcion\n";
public:
Test local_f ("local a funcion()");
Test (void); // Constructor basico
cout << "Saliendo de: funcion\n";
Test (string); // Constructor con parámetros
}
};
Test :: Test (void) {
int main(void){
msg = "VACIO";
cout << "Ejecutando : main\n";
cout << " Constructor 1 de Test " << "--> " << msg << "\n";
Test local_m ("local a main()");
}
funcion ();
Clases 17 Clases 18
Clases 19 Clases 20
if (!Coef) {
cerr << "\nError: no hay memoria\n\n"; Los datos miembro pueden iniciarse usando la sección de iniciación del
exit (1); constructor. Esta implementación realiza las mismas tareas que la anterior y su
} prototipo (declaración) es idéntica:
for (int i=0; i<= MaxGrado; i++) Coef[i] = 0.0;
} // Constructor por defecto (alternativa)
// Constructor con parametros Polinomio::Polinomio(void): MaxGrado(10),Grado(0){
Polinomio :: Polinomio (int grado){ Coef = new (nothrow) float [MaxGrado+1];
MaxGrado = grado; if (!Coef) {
Grado = 0; cerr << "\nError: no hay memoria\n\n";
Coef = new (nothrow) float [MaxGrado+1]; exit (1);
if (!Coef) { }
cerr << "\nError: no hay memoria\n\n"; for (int i=0; i<= MaxGrado; i++) Coef[i] = 0.0;
exit (1); }
}
for (int i=0; i<= MaxGrado; i++) Coef[i] = 0.0;
}
Clases 21 Clases 22
Los dos constructores presentados pueden resumirse en uno solo, haciendo uso Ejemplo: Polinomio (1)
de la posibilidad de emplear valores por defecto para los parámetros:
class Polinomio{ DemoPolinomio.cpp
......
public: #include <iostream>
// Constructor #include <iomanip>
Polinomio (int GradoMaximo = 10); #include "ModuloPolinomio.h"
...... using namespace std;
};
Polinomio :: Polinomio (int GradoMaximo): MaxGrado(GradoMaximo){ int main (void){
Grado = 0; cout.setf (ios::showpoint);
Coef = new (nothrow) float [MaxGrado+1]; cout.setf (ios::fixed);
if (!Coef) {
cerr << "\nError: no hay memoria\n\n"; Polinomio p1;
exit (1); p1.PintaPolinomio("p1 inic-def");
} p1.PonCoeficiente(2, 3.0);
for (int i=0; i<= MaxGrado; i++) Coef[i] = 0.0; p1.PintaPolinomio("p1 con coef 2=3.0");
} p1.PonCoeficiente(4,-10.5);
p1.PintaPolinomio("p1 con coef 2=3.0, 4=-10.5");
Clases 23 Clases 24
p1 con coef 2=3.0, 4=-10.5
cout << "p1(1) = " << setw(6) << setprecision(2) MaxGrado = 10 Grado = 4
<< p1.Evalua(1) << endl << endl; 3.00 X^2 -10.50 X^4
Clases 25 Clases 26
ModuloPolinomio.h ModuloPolinomio.cpp
#ifndef ModuloPolinomioH #include <iostream>
#define ModuloPolinomioH #include <iomanip>
class Polinomio{ #include <cmath>
private: #include <cstdlib>
float * Coef; #include "ModuloPolinomio.h"
int Grado; #using namespace std;
int MaxGrado; // Constructor por defecto y con parametros
public: Polinomio :: Polinomio (int GradoMaximo): MaxGrado(GradoMaximo){
Polinomio (int GradoMaximo = 10); // Constructores Grado = 0;
void PonCoeficiente (int i, float c); // Otros metodos Coef = new (nothrow) float [MaxGrado+1];
int LeeGrado (void) const; if (!Coef) {
float LeeCoeficiente (int i) const; cerr << "\nError: no hay memoria\n\n";
float Evalua (float x) const; exit (1);
void PintaPolinomio (const char * const msg) const; }
}; for (int i=0; i<= MaxGrado; i++) Coef[i] = 0.0;
#endif }
Clases 27 Clases 28
// Devuelve el grado del polinomio // Devuelve el valor del coeficiente de grado i
int Polinomio :: LeeGrado (void) const{ float Polinomio :: LeeCoeficiente (int i) const{
return (Grado); if ((i<0) && (i>MaxGrado)) {
} cerr << "\nError: grado incorrecto\n\n";
exit (1);
// Establece el valor del coeficiente de grado i }
void Polinomio :: PonCoeficiente (int i, float valor){ return (Coef[i]);
if ((i<0) && (i>MaxGrado)) { }
cerr << "\nError: grado incorrecto\n\n";
exit (1); // Muestra en cout un polinomio
} void Polinomio::PintaPolinomio (const char * const msg) const{
Coef[i] = valor; cout.setf (ios::showpoint);
if (i > Grado) Grado = i; cout.setf (ios::fixed);
} cout.setf (ios::right);
cout << msg << endl;
cout << " MaxGrado = " << setw(2) << MaxGrado;
Clases 29 Clases 30
cout << " Grado = " << setw(2) << Grado << endl;
cout << " ";
if (Coef[0]!=0) 3.4 Destructor
cout << setw(6) << setprecision(2) << Coef[0] << " ";
for (int i=1; i<=Grado; i++)
Sólo hay un destructor para una clase.
if (Coef[i]!=0)
cout << setw(6) << setprecision(2) << Coef[i] << " X^" << i << " "; Cuando un objeto deja de existir siempre se llama automáticamente al des-
cout << endl << endl ; tructor.
}
// Evalua el polinomio en el valor x Un constructor tiene el mismo nombre que la clase, precedido por el carácter ˜
float Polinomio :: Evalua (float x) const{ No admite parámetros ni devuelve ningún valor.
float res=0.0;
for (int i=1; i<=Grado; i++) Si no se especifica, el compilador proporciona un destructor de oficio. Su
if (Coef[i]!=0) res += (Coef[i]*pow(x,Grado)); implementación tiene sentido sólo cuando el constructor ha reservado memoria
return (res); dinámicamente.
}
Basta con añadir la declaración (en el fichero .h y la definición (en el fichero
.cpp) y no hay que modificar nada más.
Clases 31 Clases 32
class Polinomio{
...... 3.5 Prioridad de ejecución
public:
......
// Destructor En cuanto a los constructores:
~Polinomio (void);
...... Los objetos globales se crean primero, antes de la ejecución de cualquier
}; función (incluso main()).
A continuación se ejecuta la función main() y se crean los objetos locales a
Polinomio :: ~Polinomio (void){ ésta.
delete [] Coef;
} Cuando se llama a cualquier función y ésta empieza su ejecución se crean los
objetos locales a ella.
Importante: no hay que hacer ninguna llamada al destructor.
En cuanto a los destructores, actúan cuando un objeto deja de existir:
Clases 35 Clases 36
Test :: ~Test (void){ int main(int argc, char* argv[]){
cout << " Destructor de Test " << "----> " << msg << "\n"; cout << "Ejecutando : main\n";
} Test local_m ("local a main()");
Clases 37 Clases 38
Clases 39 Clases 40
Esto es válido en muchas ocasiones. // Constructor de copia
Polinomio::Polinomio (const Polinomio & otro){
No es válido cuando el objeto requiere memoria dinámicamente: se necesita // Copia de datos miembro
implementar un constructor de copia. MaxGrado = otro.MaxGrado;
Grado = otro.Grado;
Clases 41 Clases 42
p1 inic-def
MaxGrado = 10 Grado = 0
¿ Cómo se usa?
......
Polinomio p1; p1 con coef 2=3.0
p1.PintaPolinomio("p1 inic-def"); MaxGrado = 10 Grado = 2
p1.PonCoeficiente(2, 3.0); 3.00 X^2
p1.PintaPolinomio("p1 con coef 2=3.0");
p1.PonCoeficiente(4,-10.5); p1 con coef 2=3.0, 4=-10.5
p1.PintaPolinomio("p1 con coef 2=3.0, 4=-10.5"); MaxGrado = 10 Grado = 4
cout << "p1(1) = " << setw(6) << setprecision(2) 3.00 X^2 -10.50 X^4
<< p1.Evalua(1) << endl << endl;
...... p1(1) = -7.50
Polinomio p3 (p1);
p3.PintaPolinomio("p3 copia de p1"); p3 copia de p1
Polinomio p4 = p1; MaxGrado = 10 Grado = 4
p4.PintaPolinomio("p4 copia de p1"); 3.00 X^2 -10.50 X^4
......
p4 copia de p1
La ejecución de este código produce este resultado: MaxGrado = 10 Grado = 4
3.00 X^2 -10.50 X^4
Clases 43 Clases 44
¿Cuándo se usa el constructor de copia?
1. Cuando se declara un objeto y se inicia a partir de otro de la misma clase. 3.7 Funciones inline
Este caso ya se ha tratado.
2. Cuando una función recibe un objeto por valor.
Cada parámetro real es una variable local y se crea e inicia con el constructor La etiqueta inline indica (“sugiere” o “recomienda”) al compilador que
de copia. ponga una copia del código de esa función en el lugar donde se haga una llamada
en lugar de realizar la llamada.
3. Cuando una función devuelve un objeto.
El valor (el objeto) devuelto se creó localmente en la función. Para poder Ventaja: Tiempo de ejecución menor.
devolverse a la función que hace la llamada debe copiarse temporalmente a un
Desventaja: Programas de tamaño mayor ya que se crean varias copias del
objeto.
código.
Nuestro consejo:
Implementar siempre el constructor de copia.
Clases 45 Clases 46
Clases 47 Clases 48
// Constructor de copia
3.8 El puntero this Polinomio :: Polinomio (const Polinomio & otro){
this->MaxGrado = otro.MaxGrado;
El puntero this es una variable predefinida en todas las funciones u operadores this->Grado = otro.Grado;
miembro de una clase. Contiene la dirección del objeto concreto de la clase sobre
el cual se está aplicando la función u operador miembro. this->Coef = new (nothrow) float [(this->MaxGrado)+1];
Una función miembro (un método) de un objeto puede usar los datos miembro if (!(this->Coef)) {
empleando solamente su nombre, y no se refiere al objeto sobre el que se aplica cerr << "\nError: no hay memoria\n\n";
(éste es un argumento implı́cito). exit (1);
Si en una función u operador miembro queremos referirnos al objeto sobre el }
cual se están aplicando podemos emplear el puntero this. for (int i=0; i<= this->MaxGrado; i++)
(this->Coef)[i] = otro.Coef[i];
Puede decirse que *this es un alias del objeto. Al ser un puntero, el acceso }
a los miembros del objeto se realizará con el operador ->
Clases 49 Clases 50
Clases 51 Clases 52
Cualquier operador se sobrecarga escribiendo la definición de una función de
la manera habitual salvo que el nombre de la función es la palabra operator Es un error suponer que al sobrecargar un operador automáticamente se
seguida del sı́mbolo del operador que se sobrecarga. sobrecargan operadores relacionados.
. .* :: ?: sizeof
Clases 53 Clases 54
En ModuloPolinomio.h:
Clases 55 Clases 56
if (!Coef) { y el resultado de la ejecución es:
cerr << "\nError: no hay memoria\n\n";
exit (1); ......
} p6 asig
for (int i=0; i<= MaxGrado; i++) MaxGrado = 10 Grado = 4
Coef[i] = otro.Coef[i]; 3.00 X^2 -10.50 X^4
}
return (*this); p6(1) = -7.50
}
Obsérvese que se devuelve una referencia: la del objeto que recibe la petición
En DemoPolinomio.cpp: de asignación (*this). De esta manera se permite encadenar asignaciones.
......
Polinomio p5, p6; a=b; equivale a a.operator = (b);
p6 = p5 = p4;
a=b=c; equivale a a = (b.operator = (c));
p6.PintaPolinomio("p6 asig");
cout << "p6(1) = " << setw(6) << setprecision(2) a=b=c; NO es (a.operator = (b)) = c;
<< p6.Evalua(1) << endl << endl;
Clases 57 Clases 58
Problema: ¿Qué ocurre si el objeto al que se asigna el nuevo valor (parte izquierda
de la asignación) tiene contenido (reservó memoria dinámicamente)?
Polinomio p1;
p1.PonCoeficiente(2, 3.0);
p1.PonCoeficiente(4,-10.5);
p1.PintaPolinomio("p1");
Polinomio p2 (5);
p2.PonCoeficiente(5,2.0);
p2.PintaPolinomio("p2"); p1 y p2 antes de p1=p2 p1 y p2 después de p1=p2
p1 = p2;
Se pierde la memoria que reservó el const. de p1.
p1.PintaPolinomio("p1 despues de p1=p2");
Clases 59 Clases 60
Solución: Antes de la copia efectiva, liberar memoria:
3.9.2 Código reutilizable
Polinomio & Polinomio :: operator = (const Polinomio & otro){
if (this != &otro) { El operador = y el constructor de copia tienen prototipos parecidos (reciben una
delete [] Coef; // Liberar memoria reservada referencia constante a otro objeto de la clase):
MaxGrado = otro.MaxGrado; Polinomio & operator = (const Polinomio & otro);
Grado = otro.Grado; Polinomio (const Polinomio & otro);
......
} y realizan tareas parecidas sobre el objeto.
return (*this); Sin embargo:
}
El constructor actúa sobre un objeto que se está creando, por lo que no tiene
sentido comprobar si this != &otro
El constructor es el que reserva, inicialmente, memoria: no tiene sentido
liberarla.
Clases 61 Clases 62
Las asignaciones que se realizan entre los datos miembros son iguales ¿por-
qué no unificarlas en una función auxiliar y privada? En ModuloPolinomio.h:
Clases 63 Clases 64
En ModuloPolinomio.cpp: void Polinomio :: LiberaMemoria (void){
delete [] Coef;
void Polinomio :: Copia (const Polinomio & otro){ }
MaxGrado = otro.MaxGrado;
Grado = otro.Grado; Con esta novedad, los métodos afectados son:
PideMemoria (MaxGrado+1);
for (int i=0; i<=MaxGrado; i++) Los constructores.
Coef[i] = otro.Coef[i];
} El destructor.
void Polinomio :: PideMemoria (int n){
Coef = new (nothrow) float [n+1]; El operador de asignación.
if (!Coef) {
cerr << "\nError: no hay memoria\n\n";
exit (1);
}
}
Clases 65 Clases 66
Clases 67 Clases 68
Importante: Permitimos que p1[i] pueda emplearse, indistintamente, en la
parte derecha e izquierda (lvalue) de una asignación, por lo que la función que
3.9.3 Operador []
implementa el operador devuelve una referencia.
El objetivo es acceder a los coeficientes del polinomio empleando una notación En ModuloPolinomio.h:
similar a la del acceso a las casillas de un vector.
class Polinomio{
Ahora hacemos: Queremos: ......
p1.PonCoeficiente (0, 6.4); p1[0] = 6.4; public:
if (p1.LeeCoeficiente (i) != 0) if (p1[i] != 0) ......
float & operator [] (const int indice);
Recordar: p1[i] equivale a p1.operator[](i) ......
};
Se trata de un operador binario en el que el primer operando se modifica: se
implementa como una función miembro de la clase. El primer operando (p1)
es el objeto de la clase y es implı́cito.
Clases 69 Clases 70
En ModuloPolinomio.cpp: Problema:
float & Polinomio :: operator [] (const int indice){ La instrucción problemática “parchea” algunos casos:
if ((indice<0) && (indice>MaxGrado)) {
cerr << "\nError: grado incorrecto\n\n"; Polinomio p1; // p1.Grado = 0 p1[1] = 3.0; // p1.Grado = 1
exit (1); p1[0] = 1.0; // p1.Grado = 0 p1[4] = 4.0; // p1.Grado = 4
}
if (indice > Grado) Sin embargo, es errónea si hacemos:
Grado = indice; // !!PROBLEMA!!
p1[6] = 0.0; // p1.Grado = 6 !!NO!!
return (Coef[indice]);
}
incluso si:
cout << p1[7]; // p1.Grado = 7 !!NO!!
Conclusión: No puede mantenerse la coherencia si empleamos el dato miembro
Grado y sobrecargamos el operador []. Preferimos descartar el dato miembro
Grado y “sustituirlo” por una función privada que calcula el grado cuando sea
necesario.
Clases 71 Clases 72
En ModuloPolinomio.h: private:
int Grado (void) const;
class Polinomio{ void Copia (const Polinomio & otro);
private: void PideMemoria (int n);
float * Coef; void LiberaMemoria (void);
int MaxGrado; };
public:
// Constructores - destructor En ModuloPolinomio.cpp:
Polinomio (int GradoMaximo = 10);
Polinomio (const Polinomio & otro); Polinomio :: Polinomio (int GradoMaximo = 10): MaxGrado(GradoMaximo){
~Polinomio (void); PideMemoria (MaxGrado+1);
// Operadores sobrecargados for (int i=0; i<= MaxGrado; i++) Coef[i] = 0.0;
Polinomio & operator = (const Polinomio & otro); }
float & operator [] (const int indice);
// Otros metodos Polinomio :: Polinomio (const Polinomio & otro){
float Evalua (float x) const; Copia (otro);
void PintaPolinomio (const char * const msg) const; }
Clases 73 Clases 74
Clases 75 Clases 76
float Polinomio :: Evalua (float x) const{ void Polinomio :: PideMemoria (int n){
float res=0.0; Coef = new (nothrow) float [n+1];
int grado = Grado(); if (!Coef) {
cerr << "\nError: no hay memoria\n\n";
for (int i=1; i<=grado; i++) exit (1);
if (Coef[i]!=0) res += (Coef[i] * pow (x,i)); }
return (res); }
} void Polinomio :: LiberaMemoria (void){
delete [] Coef;
void Polinomio :: Copia (const Polinomio & otro){ }
MaxGrado = otro.MaxGrado; int Polinomio :: Grado (void) const{
int i;
PideMemoria (MaxGrado+1); bool sigo = true;
for (int i=0; i<=MaxGrado; i++) for (i=MaxGrado; (i>=0) && sigo; i--)
Coef[i] = otro.Coef[i]; if (Coef[i] != 0.0) sigo = false;
} return (i+1);
}
Clases 77 Clases 78
Se trata de un operador binario en el que los dos operandos deben ser siempre
de tipo Polinomio y donde no se modifica ningún operando:
3.9.4 Operadores aritméticos
podrı́a implementarse con una función friend o con una función miembro.
El objetivo es emplear los operadores aritméticos (+, -, etc.) para sumar,
restar, etc. datos de tipo Polinomio.
Nos decidimos por la función miembro.
Operador +
El operador + se sobrecarga con este prototipo:
Deseamos escribir: Polinomio operator + (const Polinomio & otro);
Polinomio p1, p2,p3; declarándose como una función miembro (pública) de la clase Polinomio, por lo
...... que:
p3 = p1 + p2; p3 = p1 + p2;
en lugar de: es igual que:
p3 = SumaPolinomios (p1, p2); p3 = p1.operator+(p2);
Clases 79 Clases 80
En ModuloPolinomio.cpp: Operador *
Polinomio Polinomio::operator + (const Polinomio & otro){ El operador * puede sobrecargarse para el producto de dos polinomios como antes
int MayorMaxGrado = (MaxGrado > otro.MaxGrado) ? MaxGrado : otro.MaxGrado; (función miembro):
Polinomio operator * (const Polinomio & otro);
Polinomio tmp (MayorMaxGrado);
de manera que, por ejemplo:
for(int i=0; i<= tmp.MaxGrado; i++)
tmp.Coef[i] = Coef[i] + otro.Coef[i]; p3 = p1 * p2; equivale a p3 = p1.operator * (p2);
return (tmp); Si se desea permitir, además, la multiplicación de un dato float por un polinomio:
} Polinomio p3 = p1 * 2.0;
equivale a:
Polinomio p3 = p1.operator * (2.0);
Clases 81 Clases 82
La siguiente instrucción, en cambio, sı́ provoca errores de compilación: Un operador en el que no pueda asegurarse que el primer argumento sea siempre
Polinomio p4 = 2.0 * p1;
un objeto de la clase no se implementará como una función miembro.
En el caso de un operador en el que alguna versión deba implementarse con
¿Por qué?
una función friend se recomienda sobrecargar el operador con funciones
El operador * se permitirá en estos casos: friend, con tantas versiones como casos se permitan.
1. p = p1 * p2; En ModuloPolinomio.h:
2. p = p1 * 2.0; class Polinomio
{
3. p = 2.0 * p1;
......
public:
El caso 3 no puede implementarse con una función miembro, por lo que se emplea ......
una función friend: friend Polinomio operator * (const Polinomio & p1, const Polinomio & p2);
friend Polinomio operator * (const Polinomio & p, const float c);
Una función friend de una clase puede acceder a la parte privada de esa friend Polinomio operator * (const float c, const Polinomio & p);
......
clase, aunque no sea una función miembro de la clase.
};
Clases 83 Clases 84
En ModuloPolinomio.cpp:
Polinomio operator * (const float c, const Polinomio & p){ Notas:
Polinomio tmp (p.MaxGrado);
Polinomio operator * (const Polinomio & p1, const Polinomio & p2){
// EJERCICIO
}
Clases 85 Clases 86
Clases 87 Clases 88
En ModuloPolinomio.h: En ModuloPolinomio.cpp:
ostream & operator << (ostream & out, const Polinomio & p){
class Polinomio
out.setf (ios::showpoint);
{
out.setf (ios::fixed);
......
out.setf (ios::right);
public:
int grado = p.Grado();
......
out << "---------------------------------\n";
friend ostream & operator << (ostream &, const Polinomio &);
out << " MaxGrado = " << setw(2) << p.MaxGrado;
friend istream & operator >> (istream &, Polinomio &);
out << " Grado = " << setw(2) << grado << endl;
......
cout << " ";
};
if (p.Coef[0]!=0)
out << setw(6) << setprecision(2) << p.Coef[0] << " ";
for (int i=1; i<=grado; i++)
if (p.Coef[i]!=0)
out << setw(6) << setprecision(2) << p.Coef[i] << " X^" << i << " ";
out << "\n---------------------------------\n\n";
return (out);
}
Clases 89 Clases 90
istream & operator >> (istream & in, Polinomio & p){ La ejecución de:
int ValGrado;
float ValCoef; Polinomio p1;
bool sigo = true; p1[2] = 3.0;
while (sigo) { p1[4] = -10.5;
cout << "Introduzca grado (Max = "<< p.MaxGrado << ", -1 para terminar):"; p1[0] = 1.4;
in >> ValGrado; Polinomio p2 = p1 * 2.0;
if (ValGrado < 0) cout << "p1\n" << p1;
sigo = false; cout << "p1(1) = " << setw(6) << setprecision(2) << p1.Evalua(1) << endl << endl;
else { cout << "p2 = p1 * 2.0\n" << p2;
cout << " Introduzca coeficiente de grado " << ValGrado << ": ";
in >> ValCoef; produce como resultado:
p[ValGrado] = ValCoef;
p1
}
---------------------------------
}
MaxGrado = 10 Grado = 4
return (in);
1.40 3.00 X^2 -10.50 X^4
}
---------------------------------
Clases 91 Clases 92
Introduzca grado (Max = 10, -1 para terminar): 2
p1(1) = -7.50 Introduzca coeficiente de grado 2: 22.2
Introduzca grado (Max = 10, -1 para terminar): 5
p2 = p1 * 2.0 Introduzca coeficiente de grado 5: -5.5
--------------------------------- Introduzca grado (Max = 10, -1 para terminar): 0
MaxGrado = 10 Grado = 4 Introduzca coeficiente de grado 0: 1
2.80 6.00 X^2 -21.00 X^4 Introduzca grado (Max = 10, -1 para terminar): -1
---------------------------------
p3 leido
Respecto a la lectura, la ejecución de: ---------------------------------
MaxGrado = 10 Grado = 5
Polinomio p3; 1.00 22.20 X^2 -5.50 X^5
cin >> p3; ---------------------------------
cout << "p3 leido\n" << p3;
Clases 93 Clases 94
Clases 95 Clases 96
Deberı́an iniciarse: Tambien es obligatoria, con iniciadores de miembros, la iniciación de un objeto
de otra clase que sea miembro de la clase considerada.
int VarGlobal = 10;
#include <iostream>
class UnaClase{ #include <iomanip>
private: using namespace std;
const float C;
class Clase1 {
int & ref;
private:
public: int Campo1Clase1;
UnaClase (void); int Campo2Clase1;
...... public:
}; Clase1 (int v1=0, int v2=0);
friend ostream & operator << (ostream &, const Clase1 &);
UnaClase :: UnaClase (void) : C(0.16), ref(VarGlobal){ };
......
}
Clases 97 Clases 98
class Clase2 { ostream & operator << (ostream & out,const Clase2 & o){
private: out <<"---------------------------------\n";
Clase1 Campo1Clase2; out <<"Campo1Clase2: "<< o.Campo1Clase2<< endl;
int Campo2Clase2; out <<"Campo2Clase2: "<< o.Campo2Clase2<< endl;
public: out <<"---------------------------------\n\n";
Clase2 (int v1=0, int v2=0, int v3=0); return (out);
friend ostream & operator << (ostream &, const Clase2 &); }
};
ostream & operator << (ostream & out,const Clase1 & o){
Clase1 :: Clase1 (int v1, int v2){ out <<"\n ..............................\n";
Campo1Clase1 = v1; out <<" Campo1Clase1: "<< o.Campo1Clase1<< endl;
Campo2Clase1 = v2; out <<" Campo2Clase1: "<< o.Campo2Clase1<< endl;
} out <<" ..............................\n";
return (out);
Clase2 :: Clase2 (int v1, int v2, int v3): Campo1Clase2 (v1, v2){ }
Campo2Clase2 = v3;
}
obj: obj3:
--------------------------------- ---------------------------------
Campo1Clase2: Campo1Clase2:
.............................. ..............................
Campo1Clase1: 1 Campo1Clase1: 0
Campo2Clase1: 2 Campo2Clase1: 0
.............................. ..............................
Campo2Clase2: 3 Campo2Clase2: 0
--------------------------------- ---------------------------------
Libro 1
Titulo: Primero
Paginas: 100
Libro 2
Titulo: Otro
Paginas: 200
Libro 3
Titulo: Ultimo
Paginas: 300
Libro 4
Titulo: *