C ++, модель данных, шаблоны - PullRequest
       3

C ++, модель данных, шаблоны

3 голосов
/ 21 декабря 2010

Я использую модель данных с классами: Point2D, Point3D, PointGeo:

template <class T>
class Point2D
{
    protected:
            T x;
            T y;
...
};


template <class T>
class Point3D
{
    protected:
            T x;
            T y;
            T z;
...
};

template <class T>
class PointGeo
{
    protected:
            T lat;
            T lon;
...
};

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

Список 2D точек

template <class T>
struct TPoints2DList
{
    typedef std::vector <Point2D <T> > Type;
};


template <class T>
class Points2DList
{
    private:
            typename TPoints2DList <T>::Type  points;


    public:
            Points2DList() : points ( 0 ) {}
            virtual ~Points2DList() {points.clear();}
            Points2DList ( const Points2DList &source );
            typename TPoints2DList <T>::Type ::iterator begin() { return points.begin(); }
            typename TPoints2DList <T>::Type::const_iterator begin() const { return points.begin(); }
            typename TPoints2DList <T>::Type::iterator end() { return points.end(); }
            typename TPoints2DList <T>::Type::const_iterator end() const { return points.end(); }
            Point2D <T> &operator [] ( int index ) {return points[index];}
            const Point2D <T> &operator [] ( int index ) const {return points[index];}

    public:
            //Overloaded member functions
            inline void clear() {points.clear();};
            inline void pop_back() {points.pop_back();}
            inline void push_back ( Point2D <T> p ) { points.push_back ( p );}
            inline unsigned int size() const {return points.size();}

    public:
            //Other methods
            void loadPointsFromFile ( const char *file);
...
}

Список 3D очков

template <class T>
struct TPoints3DList
{
    typedef std::vector <Point3D <T> > Type;
};


template <class T>
class Points3DList
{
    private:
            typename TPoints3DList <T>::Type  points;


    public:
            Points3DList() : points ( 0 ) {}
            virtual ~Points2DList() {points.clear();}
            Points3DList ( const Points3DList &source );
            typename TPoints3DList <T>::Type ::iterator begin() { return points.begin(); }
            typename TPoints3DList <T>::Type::const_iterator begin() const { return points.begin(); }
            typename TPoints3DList <T>::Type::iterator end() { return points.end(); }
            typename TPoints3DList <T>::Type::const_iterator end() const { return points.end(); }
            Point3D <T> &operator [] ( int index ) {return points[index];}
            const Point3D <T> &operator [] ( int index ) const {return points[index];}

    public:
            inline void clear() {points.clear();};
            inline void pop_back() {points.pop_back();}
            inline void push_back ( Point3D <T> p ) { points.push_back ( p );}
            inline unsigned int size() const {return points.size();}

    public:
            //Other methods
            void loadPointsFromFile ( const char *file);
 ...
}

Исходный код класса PointGeo похож ...

Так что различия в коде между классами невелики. Они различаются по способам загрузки, печати, сохранения данных.

Было бы неуместно разрабатывать класс, заменяющий все три класса? Как создать методы для загрузки, печати данных, специфичных для типа данных?

Аналогичная ситуация возникает для динамического размещения: Node2D, Node3D, ... классы. Класс Node2D хранит некоторые топологические отношения и использует указатели на другие узлы или грани ... В этом случае все три класса будут иметь разные деструкторы ...

Список 2D точек

template <class T>
struct TNodes2DList
{
    typedef std::vector <Node2D <T> *> Type;
};

Большое спасибо за ваши комментарии и предложения. Я пишу геометрическую библиотеку и думаю о наиболее подходящей модели данных.

Ответы [ 2 ]

4 голосов
/ 21 декабря 2010

Вы можете поместить операции ввода-вывода непосредственно в типы Point2D Point3D. Тогда вам не нужно будет создавать дополнительный класс списка, поскольку печать / чтение будет простым:

for (std::vector<Point3D>::iterator i = a.begin; i != a.end(); ++i) {
    i->print_to_file(file);
}

Если это невозможно, по крайней мере, один и тот же класс списка может использоваться в качестве шаблона для обслуживания как Point3D, так и Point2D.

1 голос
/ 21 декабря 2010

В зависимости от того, что вы делаете с классами, вы можете сделать что-то вроде:

template<class T, unsigned int count = 2>
class Point
{
public:
    T t[count];
    // other data members here
};

Однако, если вы делаете что-то вроде векторной математики (например, перекрестные произведения, точечные произведения, нормализация и т. Д.)) выполнение этого сделало бы класс намного более сложным, чем наличие двух классов (2D и 3D).Если вы не занимаетесь чем-то специализированным для класса Geo, на самом деле нет необходимости иметь другую 2D и Geo форму.

...