如何区分具有相同参数的两个构造函数?

时间:2010-03-15 09:43:57

标签: c++ parameters constructor

假设我们想要一个表示复数的类的两个构造函数:

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

但参数(数量和类型)是相同的:更优雅的方式是什么 确定意图是什么?将第三个参数添加到其中一个构造函数中?

10 个答案:

答案 0 :(得分:43)

最好添加具有适当名称的静态方法,并让它们创建对象。

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

答案 1 :(得分:36)

您不能拥有两个具有相同签名的构造函数(或任何函数)。最好的解决方案可能是为您的坐标类型创建类,并在这些类上重载。例如:

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;
};

然后你的构造者变成:

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

使用中:

Complex c( CartCoord( 1, 2 ) );

您还可以将它们与Complex类的重载运算符一起使用。例如,假设您有一个二进制+运算符,类定义为:

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

然后:

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

由于我们有一个从PolarCoord到Complex的转换构造函数,因此将在+表达式中使用。这比调用静态函数创建临时函数更自然(恕我直言)。

这是Koenig的格言(或者至少是它的一个版本)的一个例子 - 每当遇到一个难题时,引入一个新级别的类来解决它。

答案 2 :(得分:8)

在Parashift C ++常见问题解答中使用名为here的命名构造函数。

答案 3 :(得分:5)

你不能 - 如果方法签名是相同的,你就被塞满了。

当然,你总是可以为每种类型的坐标系创建一个子类,但这远非理想 - 特别是如果你以后找到一个很好的理由想要将Complex复制为其他原因......

答案 4 :(得分:3)

除了拥有两个构造函数外,您只需要一个构造函数,但需要添加第三个参数,例如:

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

'enum type'也可以有一个默认类型,所以你不必每次都提供你想要使用的坐标类型,默认情况下当然应该是最常用的坐标。

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

答案 5 :(得分:1)

我不知道它是否是C ++中的好习惯,但我会以不同的方式命名这两种方法,至少从可维护性的角度来看。

答案 6 :(得分:1)

我可能会创建更多的课程,但后来我是Boost Strong Typedef库的擅长者。

对我而言,使用double来表示坐标,模块和角度是没有意义的。

所以我会:

class CoordinateX {};
class CoordinateY {};

class Modulus {};
class Angle {};

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

而且非常清楚,并且没有歧义。您还可以在松散的意义上添加一些“单位”的编译时检查。添加X坐标和Y坐标,或者更远的距离和角度,很少有意义(如果有的话)。

答案 7 :(得分:1)

由于没有人提到它,你可以使用标签:

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);
}

答案 8 :(得分:0)

对我来说,更优雅的方法是创建一个代表笛卡尔坐标的类,另一个代表极坐标,然后将相关类的对象赋予构造函数。

这样你就会有两个使用不同参数的构造函数。

答案 9 :(得分:0)

我在练习C ++时使用这种简单的替代方法,我不知道这是否是你想要的。

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 );
    }
}