Страницы

Поиск по вопросам

пятница, 20 декабря 2019 г.

Как отличить конструкторы с одинаковой сигнатурой

#cpp #ооп #классы #конструктор


Что делать, если мой класс может иметь различные по смыслу конструкторы, но эти конструкторы
имеют одинаковую сигнатуру? Как отличить их?

struct Circle {
  Circle(float radius, float center_delta);
  Circle(float any_point_delta, float center_delta);
  Circle(float first_point_delta, float second_point_delta); 
}

    


Ответы

Ответ 1



Кратко: а никак. Длиннее: варианты - или добавлять третий параметр, который говорит, как именно строить объект, или написать фабрику - обычно статическую функцию, которая возвращает новый объект (ну, почти как конструктор :)) - и сделать их три разных с тремя разными именами.

Ответ 2



Определите перечисление, вроде: enum class CircleCstType { byRadAndDelta, // etc } и передавайте его в конструктор. В конструкторе - switch. Или же создайте фабрику для данного класса, в ней определите соответствующие методы и сделайте ее другом класса: class CircleFactory { public: Circle createByRadAndDelta(float, float); Circle createByDeltas(float, float); // etc }

Ответ 3



Способом решить данную неоднозначность - великое множество. Если ограничиться только вариантами, которые выбирают требуемый конструктор на стадии компиляции, то можно это сделать, например, введением фиктивного параметра-тэга, как это делается в некоторых стандартных классах struct by_radius_and_center_tag {} by_radius_and_center; struct by_point_and_center_tag {} by_point_and_center; struct by_first_and_second_tag {} by_first_and_second; struct Circle { Circle(float radius, float center_delta, by_radius_and_center_tag); Circle(float any_point_delta, float center_delta, by_point_and_center_tag); Circle(float first_point_delta, float second_point_delta, by_first_and_second_tag); }; ... Circle circle(10, 100, by_radius_and_center); При желании можно вообще перейти на передачу инициализирующих значений упакованными внутрь класса-оболочки struct radius_and_center_pair : std::pair { using std::pair::pair; }; struct point_and_center_pair : std::pair { using std::pair::pair; }; struct first_and_second_pair : std::pair { using std::pair::pair; }; struct Circle { Circle(const radius_and_center_pair &radius_and_center); Circle(const point_and_center_pair &point_and_center); Circle(const first_and_second_pair &first_and_second); }; ... Circle circle(radius_and_center_pair{ 10, 100 });

Ответ 4



Как вариант, можно еще определить структуры, имеющие операторы преобразования в тип float. Например: struct Point { float delta; Point(float d = 0) : delta(d) {} operator float() { return delta; } }; struct Points : Point { Points(float p) : Point(p) {} }; тогда пример вашей структуры: struct Circle { float x, y; Circle(float radius, float center_delta) : x(radius), y(center_delta){} Circle(Point any_point_delta, Point center_delta) : x(any_point_delta), y(center_delta){} Circle(Points first_point_delta, Points second_point_delta) : x(first_point_delta), y(second_point_delta){} }; и пример создания обьектов: Circle c1(2.0, 3), c2(Point(0.5), Point(1.5)), c3(Points(2), Points(3)); P.S. И как сказал пользователь Harry, варианты есть всегда(по мне не всегда, а почти всегда)...

Комментариев нет:

Отправить комментарий