Подтвердить что ты не робот

Как отличить два конструктора с одинаковыми параметрами?

Предположим, что нам нужны два конструктора для класса, представляющих комплексные числа:

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

но параметры (число и тип) одинаковы: какой изящный способ определить, что предназначено? Добавление третьего параметра в один из конструкторов?

4b9b3361

Ответ 1

Лучше добавить статические методы с соответствующими именами и позволить им создавать объекты.

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

Ответ 2

У вас нет двух конструкторов (или любых функций) с теми же сигнатурами. Лучшим решением, вероятно, является создание классов для ваших типов координат и перегрузка на них. Например:

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 to Complex, это будет использоваться в выражении+. Это более естественно (IMHO), чем вызов статических функций для создания временного..

Это пример изложения Кенига (или, по крайней мере, его версии) - всякий раз, столкнувшись с трудной проблемой, вводите новый уровень классов для его решения.

Ответ 3

Используйте именованный именованный конструктор, описанный здесь в FAQ по Parashift С++.

Ответ 4

Вы не можете - если сигнатуры метода совпадают, вы набиты.

Конечно, вы всегда можете создать подкласс для каждого типа системы координат, но это далеко не идеально - особенно если вы позже найдете веские основания хотеть подкласс Complex по другим причинам...

Ответ 5

Вместо двух конструкторов вам нужно иметь только один, но добавить третий параметр, например:

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

'тип enum' также может иметь тип по умолчанию, поэтому вам не нужно указывать, какие типы координат вы собираетесь использовать каждый раз, по умолчанию это должно быть то, что больше всего используется.

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

Ответ 6

Я не знаю, является ли это хорошей практикой в ​​С++, но я бы назвал эти два метода по-разному, по крайней мере, для точки обслуживания.

Ответ 7

Я бы, вероятно, создал больше классов, но тогда я являюсь адептом библиотеки Boost Strong Typedef.

Для меня нет смысла использовать double для представления координат, модуля и углов.

Итак, я бы:

class CoordinateX {};
class CoordinateY {};

class Modulus {};
class Angle {};

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

И там это совершенно ясно, и нет никакой двусмысленности. Также вы добавляете некоторую проверку времени "единиц" во время компиляции в свободном смысле. Очень редко (если когда-либо) имеет смысл добавить X-координату и Y-координату или, что еще хуже, расстояние и угол.

Ответ 8

Поскольку никто не упоминал об этом, вы можете использовать теги:

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

Ответ 9

Для меня более элегантным способом было бы создать класс, представляющий декартовы координаты, а другой - полярные координаты, а затем передать объект соответствующего класса конструкторам.

Таким образом, у вас будет два конструктора, использующих разные параметры.

Ответ 10

Я использую этот простой альтернативный способ, практикуя С++, я не знаю, хотите ли вы этого.

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