Article View: es.comp.lenguajes.c++
Article #53Re: Duda sobre Constructor de Copia
From: "Fernando A. Gómez F."
Date: Mon, 03 Nov 2008 18:11
Date: Mon, 03 Nov 2008 18:11
394 lines
12982 bytes
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-mailReferences:
<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