C++、数据模型、模板

发布于 2024-10-08 23:36:06 字数 3705 浏览 7 评论 0原文

我正在使用带有类的数据模型: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;
};

非常感谢您的评论和建议。我正在编写几何库并思考最合适的数据模型。

I am using a data model with classes: 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;
...
};

To manage instances of these classes the folowing classes allowing loading points from file, adding/removing points, clearing list, printing are used...

List of 2D points

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

List of 3D points

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

Source code of PointGeo class is similar...

So differences in the code between the classes are small. They differ in methods for loading, printing, saving data.

Would it be inappropriate to design a class replacing all three classes? How to create methods for loading, printing data specific for the data type?

The similar situation occurs for the dynamic alocation: Node2D, Node3D,... classes. Class Node2D stores some topological relationships and using pointers to other nodes or faces... In such case all three classes will have a different destructor...

List of 2D points

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

Thank you very much for your comments and suggestions. I am writing geometric library and thinking about the most suitable data model.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

渔村楼浪 2024-10-15 23:36:06

您可以将 I/O 操作直接放入 Point2D Point3D 类型。那么您就不必创建额外的列表类,因为打印/读取将非常简单:

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

如果这不可行,至少可以使用相同的列表类作为模板来服务 Point3D 和 Point2D

You could put the I/O operations directly to Point2D Point3D types. Then the you wouldn't have to create additional list class since printing/reading would be as simple as:

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

If this isn't viable, at least the same list class could be used as template to serve both Point3D and Point2D

謌踐踏愛綪 2024-10-15 23:36:06

根据您对类所做的操作,您可以执行以下操作:

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

但是,如果您正在执行向量数学之类的操作(例如叉积、点积、归一化等),那么这样做将使类比使用2 个类别(2D 和 3D)。除非您正在做一些专门针对 Geo 类的事情,否则实际上没有必要拥有不同的 2D 和 Geo 形式。

Depending on what you are doing with the classes, you could do something like:

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

However, if you are doing something like vector math (e.g. cross products, dot products, normalization, etc.) doing this would make the class far more complicated than having 2 classes (2D and 3D). Unless you are doing something specialized in the Geo class, there really isn't any need to have a different 2D and Geo form of it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文