[C con Clase] Error constructor copia
Steven Davidson
srd4121 en njit.edu
Mar Mar 31 19:03:31 CEST 2009
Hola Vicente,
vicente lozano wrote:
> Hola,
>
> He declarado un constructor copia, pero al hacer la asignacion de un
> new me da un error el compilador que no entiendo.
>
Ten presente que una asignación no implica un constructor copia. Por
ejemplo,
class Algo
{
public:
Algo();
Algo( const Algo &ref );
...
};
int main()
{
Algo obj1, obj2; // Constructor: Algo()
Algo obj3 = obj1; // Constructor copia: Algo(const Algo &)
obj2 = obj1; // Asignación
...
}
Las asignaciones tienen que ver con el operador de asignación y no con
el constructor. Si queremos un comportamiento diferente al de defecto
para la asignación, entonces tenemos que sobrecargar el operador de
asignación.
> Las clases son:
>
> class ProbabilityDistribution {
>
> gsl_rng * _rnd;
> DistType _distType;
> long double _mu;
> long double _sigma;
> ...
> }
>
> class Error {
> ProbabilityDistribution _components[];
Me temo que esta declaración no es correcta. O bien creaste un array o
bien un puntero; esto es,
class Error
{
ProbabilityDistribution _components[1024];
...
};
Usando un puntero, entonces sería:
class Error
{
ProbabilityDistribution *_components;
...
};
Si has declarado este miembro como un array, entonces tienes un error y
posiblemente otro. Escribes:
_components[0] = new ProbabilityDistribution( ... );
Los tipos no concuerdan; estás haciendo esto,
<ProbabilityDistribution> = <ProbabilityDistribution *>
Es decir, intentas asignar un puntero a un objeto. Como no has
sobrecargado el operador de asignación, el compilador se queja de que no
existe un candidato para este operador con los tipos de estos operandos.
Ten presente que al usar un array, ya has instanciado todos los objetos
según la cantidad del array. Siguiendo el ejemplo que he dado, hemos
instanciado 1024 objetos de la clase 'ProbabilityDistribution' invocando
el constructor 'ProbabilityDistribution()' - sin parámetros.
Si en su lugar, '_components' es un puntero, entonces, no tendríamos un
problema, ya que los tipos de los operandos en la asignación concuerdan;
esto es,
<ProbabilityDistribution *> = <ProbabilityDistribution *>
Sin embargo, apuntaríamos a un solo objeto, sin tener una lista de objetos.
Aconsejo crear un array dinámico de punteros a
'ProbabilityDistribution'. Esto es,
class Error
{
ProbabilityDistribution **_components;
...
};
Luego, haríamos esto:
// Creamos el array dinámicamente
_components = new ProbabilityDistribution*[1024];
// Instanciamos un objeto para el primer elemento
_components[0] = new ProbabilityDistribution( ... );
Esto implica que tenemos que liberar la memoria, posiblemente para el
destructor.
La otra posibilidad es declarar un array (estático) de punteros. Esto sería,
class Error
{
ProbabilityDistribution *_components[1024];
...
};
Con esto, creamos un array de punteros y luego instanciaremos cada
objeto de cada elemento dinámicamente, según nos interese. Esto es,
_components[0] = new ProbabilityDistribution( ... );
En C++, aconsejaría usar una clase-plantilla estándar que realice estas
operaciones. Por ejemplo, podrías usar un 'vector<>' que viene a
representar un array cualquiera. Por ejemplo,
#include <vector>
class Error
{
vector< ProbabilityDistribution > _components;
...
};
También podrías crear un 'vector' de punteros. Esto es,
class Error
{
vector< ProbabilityDistribution * > _components;
...
};
Así, puedes instanciar cada objeto dinámicamente.
> int _ncomponents;
> long double _lastError;
> ...
> }
>
>
> Se usa la libreria GSL, libreria matematica que me recomendasteis por
> aqui, pero el error creo que no tiene nada que ver, lo digo solo
> para que sepais de donde viene el gsl_rng y tal.
>
No veo error en la GSL, pero sí veo un problema con 'gsl_rng *' en la
clase 'ProbabilityDistribution'. Siempre que diseñes una clase que
contenga miembros que son punteros, deberías definir un constructor
copia y sobrecargar el operador de asignación. De lo contrario, estarás
copiando punteros y no la información apuntada por ello. Esto se llama
una copia de poca o baja profundidad. Lo que interesa es hacer una copia
profunda, siguiendo los punteros y copiando toda la información.
Espero haber aclarado las dudas.
Steven
Más información sobre la lista de distribución Cconclase