Un objeto con un puntero interno
Modifiquemos la clase Caja para que incluya un puntero a una variable entera como atributo privado.
#include <iostream.h>
class Caja {
double longitud, anchura, altura;
int *point;
public:
Caja(double dim1, double dim2, double dim3, int valorAlmacenado);
~Caja();
double volumen(void) {return longitud * anchura * altura;} // Inline
int getValor(void) {return *point;} // Inline
};
//Implementation del constructor
Caja::Caja(double dim1, double dim2, double dim3, int valorAlmacenado)
{
longitud = dim1;
anchura = dim2;
altura = dim3;
point = new int;
*point = valorAlmacenado;
}
Caja::~Caja(void) //Destructor
{
delete point;
}
main()
{
Caja pequeñ(5, 4, 10, 1), mediana (10, 6, 20, 2), grande(20, 10, 30, 3);
cout << "El volumen de la caja pequeña es " << pequeña.volumen() << "\n";
cout << "El volumen de la caja mediana es" << mediana.volumen() << "\n";
cout << "El volumen de la caja grande es" << grande.volumen() << "\n";
cout << "El valor almacenado en la caja pequeña es " <<
pequeña.getValor() << "\n";
cout << "El valor almacenado en la caja mediana es" <<
mediana.get_valor() << "\n";
cout << "El valor almacenado en la caja grande es " <<
grande.get_valor() << "\n";
}
El resultado de la ejecución será:
El volumen de la caja pequeña es 200
El volumen de la caja mediana es es 1200
El volumen de la caja grande es 6000
El valor almacenado en la caja pequeña es 1
El valor almacenado en la caja mediana es 2
El valor almacenado en la caja grande es 3
- Declaramos como atributo privado de la clase point, un puntero a un entero. Pero en la
declaración no estamos asociando memoria a este puntero. Es en el constructor donde
dinámicamente reservamos memoria para un entero, utilizando el operador new.
- Declaramos tres objetos, pequeña, mediana, y grande, del tipo Caja. Cada uno de ellos
contiene un puntero que apunta a tres localizaciones de memoria diferentes. Cada objeto tiene su
propia variable dinámicamente reservada para su uso privado. Además, en esta variable
dinámicamente reservada se almacena el valor entero pasado al constructor.
- En un programa pequeño como éste, no se agotará la memoria, por tanto
no es necesario comprobar que existe memoria disponible. En programas largos, sería
conveniente comprobar que el valor del puntero devuelto no es NULL, para asegurar que los datos
están realmente reservados.
- Hemos definido un destructor que borra con delete la memoria reservada dinámicamente
con new. El destructor es llamado cuando los objetos que hemos definido (pequeña, mediana y
grande) abandonan el bloque en el que han sido definidos. Si no hubiésemos definido el
destructor, al salir de la función, quedarían en la memoria las tres variables
reservadas dinámicamente sin nada apuntando a ellas. Por esta razón, el destructor se
utiliza para borrar la variable a la que el puntero apunta cuando cada objeto sale de su
ámbito de definición.
- En este caso particular, las variables serían automáticamente liberadas al
volver al sistema operativo. Pero si se tratara de una función que llama a otra
función, estaríamos llenando la memoria.
- Recordemos que si hubiésemos reservado memoria para más de un entero, por
ejemplo:
p = new int [4];
en el destructor la liberarímos de la siguiente forma:
delete [] p;
- Mencionemos de nuevo que las funciones declaradas inline deben ser utilizadas cuando la
rapidez es lo más importante en el programa, ya que el código de la función se
reescribe en el lugar en que se utiliza, y no se produce una llamada a una función definida
de forma independiente. Definimos entonces el código como parte de la declaración de
la clase, no en la implementación de las funciones. Si el código de la función
es demasiado largo, el compilador puede ignorar el requisito de inline y tratarla como un
método implementado independientemente, pero lo hará de forma invisible al usuario.
Las funciones inline violan el principio de protección de la información, ya que el
se hace el código de la función visible al usuario.