Использование шаблонов для 2D / 3D точки - PullRequest
0 голосов
/ 15 октября 2010

Стоит ли писать классы, представляющие 1D, 2D, 3D точки, используя шаблоны

template <class T>
class Point2D
{

protected:

    T X, Y;

public:

    Point2D(const T x, const T y) : hot smileyx), Y(y)) {}
    ...
};


template <class T>
class Point3D : public Point2D<T>
{
    protected:
    T Z;

public:

    Point3D(const T x, const T y, const T z) : Point2D<T>(x,y), Z(z) {}
...
};

... или используя этот подход:

class Point2D
{

protected:

    double X, Y;

public:

    Point2D(const double x, const double y) : X(x), Y(y)) {}
    ...
};



class Point3D : public Point2D
{
    protected:
    double Z;

public:

   Point3D(const double x, const double y, const double z) : Point2D(x,y), Z(z) {}
...
};

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

Этот класс предназначен не только для одноразового использования, но он будет частью библиотеки ... И моя вторая часть вопроса. Как должны быть реализованы некоторые функции «измерения»?

template <class T>
T getDist(const Point2D <T> * p1, const Point2D<T> *p2)
{
....
}

или

double  getDist(const Point2D <T> * p1, const Point2D<T> *p2)
{
....
}

Разумно ли писать такую ​​функцию вообще или для какого-то определенного типа?

Ответы [ 5 ]

6 голосов
/ 15 октября 2010

Зачем повторяться?Большая часть содержимого этих классов и функций будет одинаковой.

Что-то вроде этого работает намного лучше:

template <std::size_T N, typename T>
class Point
{
public:
    Point()
    {
        std::fill_n(mData, N, T());   
    }

    explicit Point(const T& pX) :
    mData[0](pX)
    {
        // or some variant (enable_if also works)
        static_assert(N == 1, "X constructor only usable in 1D");
    }


    explicit Point(const T& pX, const T& pY) :
    mData[0](pX),
    mData[1](pY),
    {
        static_assert(N == 2, "XY constructor only usable in 2D");
    }

    // incomplete, left as exercise for reader. :P

private:
    T mData[N];
};

И вы просто используете циклы для функций:

template <std::size_T N, typename T>
T getDist(const Point<N, T>& pFirst, const Point<N, T>& pSecond)
{
    // generic, compiler will unroll loops
}
2 голосов
/ 15 октября 2010

Исходя из своего опыта, я бы не стал, как чума, создавать иерархию классов, где 3D-точка IS-A 2D-точка.Это делает слишком легким непреднамеренное и бесшумное обращение 3D-точек к 2D-точкам.Лучше хранить координаты разных размерностей разных типов (согласно ответу GMan) и требовать явного приведения между типами.

Моя любимая в настоящее время реализация такого рода вещей обеспечивается Eigen .Даже если его лицензия (LGPL) ограничивает его использование для вас, я бы посоветовал взглянуть на его элегантно заданные векторные и матричные типы и извлечь из них уроки.

1 голос
/ 15 октября 2010

Я столкнулся с этой ситуацией, и у меня была причина разрешить разные типы значений X и Y, где X иногда был целым, но Y всегда имел более высокую точность (с плавающей запятой или двойной в зависимости от использования).Возможно, стоит подумать об этом заранее.

1 голос
/ 15 октября 2010

Мне кажется, что все в порядке, если все функции реализованы правильно и эффективно Для измерения расстояния:

template <class T>
T getDist(const Point3D <T>& p1, const Point3D<T>& p2);

подпись должна быть использована. Расстояния также могут быть в 3D.

0 голосов
/ 15 октября 2010

Некоторое внимание следует также уделить тому, как будет использоваться класс. Вы упомянули матрицы. Если вы планируете решать системы с использованием этого класса или чего-либо еще, включая матричные инверсии (или другие подобные матричные операции), представляющие матрицу в виде набора целых чисел, было бы странно.

Если вы планируете использовать его как просто таблицу сортов (или собираетесь только добавлять / вычитать и умножать матрицы), то вы можете создать шаблон класса, потому что матрица, полная целых чисел, не даст странных (и неправильных) результаты для этих операций.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...