constructors c++ parameters constructor

c++ - constructors - constructor class



¿Cómo diferenciar dos constructores con los mismos parámetros? (10)

Supongamos que queremos dos constructores para una clase que representa números complejos:

Complex (double re, double img) // construct from cartesian coordinates Complex (double A, double w) // construct from polar coordinates

pero los parámetros (número y tipo) son los mismos: ¿cuál es la forma más elegante de identificar lo que se pretende? ¿Agregar un tercer parámetro a uno de los constructores?


En lugar de tener dos constructores, necesita tener solo uno, pero agregue un tercer parámetro, por ejemplo:

Complex (double re, double img, enum type) { if(type == polar) { ..treat as polar coordinates.. } else { ..treat as cartesian coordinates.. } }

''enum type'' también puede tener un tipo predeterminado, por lo que no es necesario que proporciones el tipo de coordenadas que pretendas usar cada vez; el valor predeterminado debería ser, por supuesto, el más utilizado.

Complex (double re, double img, enum type = polar);


Es mejor agregar métodos estáticos con nombres apropiados y dejarlos para crear los objetos.

static Complex createFromCartesian(double re, double img); static Complex createFromPolar(double A, double w);


No puede tener dos constructores (ni ninguna función) con las mismas firmas. La mejor solución es, probablemente, crear clases para sus tipos de coordenadas y sobrecargarlas. Por ejemplo:

struct CartCoord { CartCoord( double re, double img ) : mRe(re), mImg(img) {} double mRe, mImg; }; struct PolarCoord { PolarCoord( double a, double v ) : mA(a), mV(v) {} double mA, mV; };

Entonces tus constructores se convierten en:

Complex( const CartCoord & c ); Complex( const PolarCoord & c);

En uso:

Complex c( CartCoord( 1, 2 ) );

También puede usarlos con operadores sobrecargados de la clase Complex. Por ejemplo, suponiendo que tiene un operador binario + para la clase, defina como:

Complex operator+( const Complex &, const Complex & );

entonces:

Complex a( CartCoord( 0, 0 ) ); Complex b = a + PolarCoord( 1, 1 );

Como tenemos un constructor de conversión de PolarCoord a Complex, esto se usará en la expresión +. Esto es más natural (en mi humilde opinión) que llamar a funciones estáticas para crear el temporal ..

Este es un ejemplo del dictamen de Koenig (o al menos una versión): cuando se enfrente a un problema difícil, presente un nuevo nivel de clases para resolverlo.


No sé si es una buena práctica en C ++ pero nombraría estos dos métodos de manera diferente, al menos para un punto de vista de mantenimiento.


No se puede: si las firmas de método son iguales, estás relleno.

Por supuesto, siempre puedes crear una subclase para cada tipo de sistema de coordenadas, pero eso está lejos de ser ideal, especialmente si luego encuentras una buena razón para querer crear una subclase de Complejo por otras razones ...


Para mí, la manera más elegante sería crear una clase que represente coordenadas cartesianas y otra que represente coordenadas polares, luego dar el objeto de la clase relevante a los constructores.

De esta forma, tendrías dos constructores usando diferentes parámetros.


Probablemente crearía más clases, pero luego soy un experto en la biblioteca Boost Strong Typedef .

Para mí no tiene sentido utilizar el double para representar tanto coordenadas, módulos y ángulos.

Entonces yo tendría:

class CoordinateX {}; class CoordinateY {}; class Modulus {}; class Angle {}; class Complex { public: Complex(CoordinateX, CoordinateY); Complex(Modulus, Angle); };

Y ahí está perfectamente claro, y no hay ambigüedad. También agrega un control de tiempo de compilación de "unidades" en un sentido amplio. Rara vez tiene sentido (si alguna vez) agregar una coordenada X y una coordenada Y, o peor una distancia y un ángulo.


Use la terminología de constructor nombrada que se describe aquí en las preguntas frecuentes de Parashift C ++.


Utilizo esta forma alternativa simple mientras practico C ++, no sé si es lo que quieres.

class Vector{ public: float x, y; Vector(); Vector(float , float, bool); float get_distance(Vector v); // find distance from another vector float get_magnitude(); // find distance from origin point Vector add(Vector v); Vector subtract(Vector v); Vector multiply(Vector v); // multiply by vector Vector multiply(float scalar); // multiply by scalar float get_angle(); }; Vector::Vector(float a, float b, bool is_cartesian = true){ if(is_cartesian){ x = a; y = b; } else{ x = a * cos( b ); y = a * sin( b ); } }


Como nadie lo mencionó, puedes usar etiquetas:

class Complex{ struct CartCoord{}; struct PolarCoord{}; Complex( CartCoord, double re, double img); Complex( PolarCoord, double a, double v); }; int main(){ auto c1 = Complex(Complex::CartCoord{}, 5, 6); auto c2 = Complex(Complex::PolarCoord{}, 5, 6); }