🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: es.comp.lenguajes.c++
Article #53

Re: Duda sobre Constructor de Copia

#53
From: "Fernando A. Gómez F."
Date: Mon, 03 Nov 2008 18:11
394 lines
12982 bytes
Empecinado wrote:
> Hola tengo una duda sobre un constructor de copia muy b�sico que he de
> implementar:
> Tengo estas dos clases:
> 
> ---------------------------------------------
> Clinica
> ---------------------------------------------
> - nombre
> - Especialidad* especialidades
> .....
> ---------------------------------------------
> y
> 
> ---------------------------------------------
> Especialidad
> ---------------------------------------------
> - nombre
> .....
> ---------------------------------------------
> 
> C�mo vemos en Cl�nica puede tener varias especialidades (Especialidad*
> especialidades) mi duda ser�a la siguiente:
> 
>   �C�mo elaboro el constructor de copia de la Clase Cl�nica?
> 

Hola. Pues no entiendo por qu� una cl�nica puede tener varias 
especialidades. Como yo lo veo, tienes un puntero a Especialidad, una 
sola especialidad. El primer ejemplo muetra este caso.

Ahora, supongo que te refer�as a que Especialidad* es un array de 
especialidades. Pues bueno, en tal caso tendr�as que iterar sobre cada 
elemento. Puedes emplear alg�n algoritmo de iteradores, como 
std::for_each. Pero asumo que est�s trabajando de forma manual. El 
ejemplo2.cpp asume este hecho. Nota en particular todos los desmadres 
que hay que hacer para obtener tama�os, etc�tera. Ciertamente se 
complica mucho m�s el asunto, y dado que aqu� solo nos interesa el 
constructor copia, no puse validaciones extras ni dem�s funcionalidad. 
Tambi�n toma en cuenta que el array de especialidades que se guarda en 
la clase Clinica es un array de valores, no de punteros (por eso tuvimos 
que definir el operador de asignaci�n). De ser as�, tendr�as que 
modificar tu tipo de dato (Especialidad**). En fin, creo que captas la 
idea.

Y finalmente, en verdad ser�a mejor que emplearas std::vector o 
std::list en lugar de andar reinventando la rueda. El ejemplo3.cpp 
muestra como ser�a en este caso.

Saludos,
Fernando.

=== EJEMPLOS ===

/*** ejemplo1.cpp ***/
#include <string>
#include <iostream>

using std::string;
using std::cout;
using std::cin;
using std::endl;

class Especialidad
{
   private:
     string _nombre;

   public:
     Especialidad() { }
     Especialidad(const string& nombre) { _nombre = nombre; }
     Especialidad(const Especialidad& especialidad) {
       _nombre = especialidad._nombre;
     }

     string nombre() const { return _nombre; }
     void nombre(const string& nombre) { _nombre = nombre; }
};

class Clinica
{
   private:
     string _nombre;
     Especialidad* _especialidad;

   public:
     // constructor default
     Clinica() {
       _especialidad = NULL;
     }

     // constructor copia
     Clinica(const Clinica& clinica) {
       _nombre = clinica._nombre;
       _especialidad = new Especialidad(*clinica._especialidad);
         // nos apoyamos en el constructor copia de Especialidad.
     }

     ~Clinica() {
       if (_especialidad != NULL) {
         delete _especialidad;
         _especialidad = NULL;
       }
     }

     string nombre() const { return _nombre; }
     void nombre(const string& nombre) { _nombre = nombre; }
     Especialidad* const especialidad() const { return _especialidad; }
     Especialidad* const especialidad() { return _especialidad; }
     void especialidad(Especialidad* especialidad) {
       _especialidad = especialidad;
     }
};

void imprimeClinica(const string& titulo, const Clinica* clinica)
{
   cout << "*** " << titulo << " ***" << endl;
   cout << "clinica: " << clinica->nombre() << endl;
   cout << "especialidad: " << clinica->especialidad()->nombre() << endl;
   cout << "*** ***\n" << endl;
}

int main()
{
   Clinica* clinica1;
   Clinica* clinica2;

   // creamos primer objeto
   clinica1 = new Clinica();
   clinica1->nombre("clinica 1");
   clinica1->especialidad(new Especialidad("especialidad 1"));
   imprimeClinica("creacion objeto", clinica1);

   // creamos el segundo objeto como copia del primero
   clinica2 = new Clinica(*clinica1); // invocamos constructor copia
   imprimeClinica("copia objeto", clinica2);

   // el primer objeto no est� ligado con el segundo.
   clinica1->nombre("otra clinica");
   clinica1->especialidad()->nombre("otra especialidad");
   imprimeClinica("primer objeto modificad", clinica1);
   imprimeClinica("segundo objeto no se modifica", clinica2);

   delete clinica1;
   delete clinica2;

   cin >> string();

   return 0;
}

/*** ejemplo2.cpp ***/

#include <string>
#include <iostream>

using std::string;
using std::out_of_range;
using std::cout;
using std::cin;
using std::endl;

class Especialidad
{
   private:
     string _nombre;

   public:
     Especialidad() { }
     Especialidad(const string& nombre) { _nombre = nombre; }
     Especialidad(const Especialidad& especialidad) {
       _nombre = especialidad._nombre;
     }

     string nombre() const { return _nombre; }
     void nombre(const string& nombre) { _nombre = nombre; }
     Especialidad& operator= (const Especialidad& especialidad) {
       _nombre = especialidad._nombre;
       return *this;
     }
};

class Clinica
{
   private:
     string _nombre;
     Especialidad* _especialidades;
     int _cuenta;

   public:
     // constructor default
     Clinica() {
       _especialidades = NULL;
       _cuenta = 0;
     }

     // constructor copia
     Clinica(const Clinica& clinica) {
       _cuenta = clinica._cuenta;
       _nombre = clinica._nombre;

       _especialidades = new Especialidad[_cuenta];
       for (int i = 0; i < _cuenta; i++)
         _especialidades[i] = clinica.obtenerEspecialidad(i);
     }

     ~Clinica() {
       if (_especialidades != NULL) {
         delete [] _especialidades;
         _especialidades = NULL;
       }
     }

     string nombre() const { return _nombre; }
     void nombre(const string& nombre) { _nombre = nombre; }
     int cuentaEspecialidades() const { return _cuenta; }

     void especialidades(Especialidad* especialidades, int cuenta) {
       _especialidades = especialidades;
       _cuenta = cuenta;
     }
     Especialidad& obtenerEspecialidad(int posicion) {
       if (posicion < 0 || posicion >= _cuenta)
         throw out_of_range("posicion fuera de rango.");
       return _especialidades[posicion];
     }
     Especialidad& obtenerEspecialidad(int posicion) const {
       if (posicion < 0 || posicion >= _cuenta)
         throw out_of_range("posicion fuera de rango.");
       return _especialidades[posicion];
     }
};

void imprimeClinica(const string& titulo, const Clinica* clinica)
{
   cout << "*** " << titulo << " ***" << endl;
   cout << "clinica: " << clinica->nombre() << endl;
   for (int i = 0; i < clinica->cuentaEspecialidades(); i++)
     cout << " - " << clinica->obtenerEspecialidad(i).nombre() << endl;
   cout << "*** ***\n" << endl;
}

int main()
{
   Clinica* clinica1;
   Clinica* clinica2;
   Especialidad* especialidades;

   // creamos lista de especialidades
   especialidades = new Especialidad[3];
   especialidades[0].nombre("especialidad 1");
   especialidades[1].nombre("especialidad 2");
   especialidades[2].nombre("especialidad 3");

   // creamos primer objeto
   clinica1 = new Clinica();
   clinica1->nombre("clinica 1");
   clinica1->especialidades(especialidades, 3);
   imprimeClinica("creacion objeto", clinica1);

   // creamos el segundo objeto como copia del primero
   clinica2 = new Clinica(*clinica1); // invocamos constructor copia
   imprimeClinica("copia objeto", clinica2);

   // el primer objeto no est� ligado con el segundo.
   clinica1->nombre("otra clinica");
   clinica1->obtenerEspecialidad(0).nombre("otra especialidad 1");
   clinica1->obtenerEspecialidad(1).nombre("otra especialidad 2");
   clinica1->obtenerEspecialidad(2).nombre("otra especialidad 3");
   imprimeClinica("primer objeto modificad", clinica1);
   imprimeClinica("segundo objeto no se modifica", clinica2);

   delete clinica1;
   delete clinica2;

   cin >> string();

   return 0;
}

/*** ejemplo3.cpp ***/

#include <string>
#include <iostream>
#include <vector>

using std::string;
using std::vector;
using std::cout;
using std::cin;
using std::endl;

class Especialidad
{
   private:
     string _nombre;

   public:
     Especialidad() { }
     Especialidad(const string& nombre) { _nombre = nombre; }
     Especialidad(const Especialidad& especialidad) {
       _nombre = especialidad._nombre;
     }

     string nombre() const { return _nombre; }
     void nombre(const string& nombre) { _nombre = nombre; }
     Especialidad& operator= (const Especialidad& especialidad) {
       _nombre = especialidad._nombre;
       return *this;
     }
};

class Clinica
{
   private:
     string _nombre;
     vector<Especialidad> _especialidades;

   public:
     // constructor default
     Clinica() { }

     // constructor copia
     Clinica(const Clinica& clinica) {
       _nombre = clinica._nombre;
       _especialidades = clinica._especialidades;
     }

     ~Clinica() {  }

     string nombre() const { return _nombre; }
     void nombre(const string& nombre) { _nombre = nombre; }
     int cuentaEspecialidades() const { return _especialidades.size(); }
     vector<Especialidad>& especialidades() { return _especialidades; }
     const vector<Especialidad>& especialidades() const { return 
_especialidades; }
     void especialidades(const vector<Especialidad>& especialidades) {
       _especialidades = especialidades;
     }
     Especialidad& obtenerEspecialidad(int posicion) {
       return _especialidades.at(posicion);
     }
     const Especialidad& obtenerEspecialidad(int posicion) const {
       return _especialidades.at(posicion);
     }
};

void imprimeClinica(const string& titulo, const Clinica* clinica)
{
   vector<Especialidad>::const_iterator i;
   cout << "*** " << titulo << " ***" << endl;
   cout << "clinica: " << clinica->nombre() << endl;
   for (i = clinica->especialidades().begin(); i != 
clinica->especialidades().end(); ++i)
     cout << " - " << i->nombre() << endl;
   cout << "*** ***\n" << endl;
}

int main()
{
   Clinica* clinica1;
   Clinica* clinica2;

   // creamos primer objeto
   clinica1 = new Clinica();
   clinica1->nombre("clinica 1");
   clinica1->especialidades().push_back(Especialidad("especialidad 1"));
   clinica1->especialidades().push_back(Especialidad("especialidad 2"));
   clinica1->especialidades().push_back(Especialidad("especialidad 3"));
   imprimeClinica("creacion objeto", clinica1);

   // creamos el segundo objeto como copia del primero
   clinica2 = new Clinica(*clinica1); // invocamos constructor copia
   imprimeClinica("copia objeto", clinica2);

   // el primer objeto no est� ligado con el segundo.
   clinica1->nombre("otra clinica");
   clinica1->especialidades().at(0).nombre("otra especialidad 1");
   clinica1->especialidades().at(1).nombre("otra especialidad 2");
   clinica1->especialidades().at(2).nombre("otra especialidad 3");
   imprimeClinica("primer objeto modificad", clinica1);
   imprimeClinica("segundo objeto no se modifica", clinica2);

   delete clinica1;
   delete clinica2;

   cin >> string();

   return 0;
}

 Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
                http://www.usenet.com
Technical Details
Message-ID: <1225743008_323574@news.usenet.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news2.google.com!news.glorb.com!news2!nlpi057.nbdc.sbc.com!prodigy.net!news-out.superfeed.net!sp6iad.superfeed.net!not-for-mail
References: <e8bea3a4-71ef-41ed-86d6-64e93538c36e@c2g2000pra.googlegroups.com>

Show Full Headers
Complete Article Headers
X-Google-Thread: f53ec,80b42ba1e6d86380
X-Google-Attributes: gidf53ec,domainid0,public,usenet
X-Google-Language: SPANISH,ASCII
Subject: Re: Duda sobre Constructor de Copia
From: "Fernando A. Gómez F."
 <fernando.a.gomez.f@gmail.com>
Date: Mon, 03 Nov 2008 12:11:07 -0600
Message-ID: <1225743008_323574@news.usenet.com>
References: <e8bea3a4-71ef-41ed-86d6-64e93538c36e@c2g2000pra.googlegroups.com>
Lines: 412
Organization: Usenet.com
Path: arc1-ca.pugleaf.net!g2news1.google.com!news2.google.com!news.glorb.com!news2!nlpi057.nbdc.sbc.com!prodigy.net!news-out.superfeed.net!sp6iad.superfeed.net!not-for-mail
Newsgroups: es.comp.lenguajes.c++
X-Proxy-User: $$ghy2trs_j
User-Agent: Thunderbird 2.0.0.17 (Windows/20080914)
MIME-Version: 1.0
In-Reply-To: <e8bea3a4-71ef-41ed-86d6-64e93538c36e@c2g2000pra.googlegroups.com>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 8bit
X-Report: Please report illegal or inappropriate use to <abuse@usenet.com>. Forward a copy of ALL headers INCLUDING the body. (DO NOT SEND ATTACHMENTS)
X-Comments2: IMPORTANT:  Usenet.com does not condone,support,nor tolerate spam nor illegal or copyrighted postings and or activity through it's network.
X-Comments: This message was posted through Usenet.com