Создание класса Point в C++
-
03-07-2019 - |
Вопрос
Прямо сейчас я использую std::pair для представления 2d-точки в С++.Однако меня раздражает необходимость писать
typedef std::pair<double, double> Point;
Point difference = Point(p2.first - p1.first,
p2.second - p1.second);
вместо возможности перегружать оператор+ и оператор-.
Итак, мой вопрос: нужно ли мне создавать класс Point?
- Публично вывести из std::pair и добавить свои собственные функции-члены?Это хорошо, потому что весь мой код может остаться прежним.Я не собираюсь делать ничего подобного
std::pair<double, double>* p = new Point;
поэтому мне не нужно беспокоиться о таких вещах, как виртуальные деструкторы. - Создайте свой собственный класс Point, что раздражает, поскольку я дублирую функциональность std::pair, однако я «делаю это в чистом виде».
- Создайте шаблонные специализации оператора+ и оператора- для std::pair, которые, честно говоря, я не помню, находятся ли они в исходных файлах или файлах заголовков.
Я думаю, это подлежит обсуждению, мне бы очень хотелось сделать № 1, но я не знаю, плохая ли это идея, поскольку я слышал, что наследование от STL запрещено.
Решение
Вы можете создать свой собственный класс Point, но использовать для внутреннего хранения данных std::pair.Это предотвращает проблему наследования от STL, но по-прежнему использует функциональность std::pair.
Другие советы
Лучше, чем кататься самостоятельно:возьмите существующую бесплатную библиотеку векторов/точек.Одна рекомендация:тот, который прикреплен к Основная математика для программистов игр.Вы можете использовать любую библиотеку, которую найдете, в качестве отправной точки, а затем оптимизировать/специализировать/настраивать ее оттуда.
Я бы предпочел создать собственный класс Point и использовать либо частное наследование, либо композицию, если вы хотите использовать функциональность std::pair.Проблема с typedef (я уверен, вы знаете) заключается в том, что любая написанная вами функция, принимающая Point, также будет использоваться чем-либо, представленным как std::pair<double, double>, что может быть недопустимым.
Имея это в виду, существует другой вариант: просто создать несколько бесплатных функций компоновщика, таких как
Point addPoints(const Point& p1, const Point& p2);
Point diffPoints(const Point& p1, const Point& p2);
(имена функций могли бы быть лучше).
Еще один вариант может заключаться в том, чтобы сделать вас собственным классом Point и сделать так, чтобы ваш класс «владел» std::pair, который представляет координаты точки.
Во многих случаях отношение «HAS A» (композиция) предпочтительнее отношения «IS A» (наследование).
Я думаю, что в «Лучших практиках» предлагается создать собственный класс Point.Таким образом, вы сможете значительно упростить работу с 3D в будущем.
Частное наследование, иначе говоря, наследование реализации, — ваш друг.
Это логически следует:Point НЕ является std::pair, вы не хотите иметь публичное преобразование с повышением из Point в std::pair, но вы хотите использовать внутренние компоненты std::pair.
Другая возможность связана с отношением «имеет» или композицией:каждая точка имеет частную std::pair, которую она использует внутри себя.
На самом деле, между композицией и частным наследованием нет большой разницы, за исключением того, что в последнем вы можете принудительно выполнить приведение к std::pair в функции-члене Point.
Создайте свой собственный класс Point.Это позволит вам делать с ним любые вещи в будущем.В частности, я уже решал подобные проблемы раньше и нашел полезным определить собственную структуру Point и создать класс Point, который наследуется от нее.
Полное раскрытие:Мне не очень нравится STL.
Не наследуйте публично от std::pair, потому что у std::pair есть оператор <, но у вашего Point его не должно быть.