【问题标题】:C++ inheritance/template questionC++ 继承/模板问题
【发布时间】:2010-07-12 15:35:46
【问题描述】:

我有两个类,点和像素:

class point {
    public:
        point(int x, int y) : x(x), y(y) { };
    private:
        int x, y;
}

template <class T>
class pixel : public point {
    public:
        pixel(int x, int y, T val) : point(x, y), val(val) { };
    private:
        T val;
}

现在这是我的问题。我想创建一个容器类(我们称之为 coll),它有一个私有的点或像素向量。如果 coll 的实例包含像素,我希望它有一个 toArray() 方法,它将其像素向量转换为表示向量内容的 T 数组。

我打算通过继承来做到这一点:即,我可以创建一个包含点向量的基类 coll 和一个包含额外方法的派生类,但是我似乎遇到了问题,因为像素是一个类模板。

有人有建议吗?我可以通过将 coll 设为类模板来以某种方式做到这一点吗?

【问题讨论】:

  • 我认为coll 也应该是一个模板类。然后,您可以将 coll 部分专门化为点和像素。
  • 像素是一组坐标(即继承“点”)还是有坐标(即包含点的实例)?
  • 我认为要提出适当的设计建议,了解“coll”类的用途会很有帮助。我认为,特别是包含的私有向量的含义很重要。

标签: c++ inheritance templates oop


【解决方案1】:

问题:你的意思是私有向量同时包含点和像素,还是只包含一个或另一个?

问题:如果只是一个或另一个,你的意思是在同一个私有向量中混合具有不同模板参数的像素?

假设它只是私有向量中的点或像素,并且私有向量中的像素都具有相同的模板参数,您可以这样做:

template < class T > class CollectionBase
{
   //common interface here
   protected:
   std::vector<T> coll_vec;
};

class PointCollection : public CollectionBase<Point>
{
   public:
   ...
};

template< class T> PixelCollection : public CollectionBase<Pixel<T> >
{
   public:
    Pixel<T>* toArray();

    ...

};

【讨论】:

  • 答案:仅此而已。答:只是具有相同模板参数的像素。这个解决方案看起来不错,但我的集合将具有许多相同的功能:这是否需要大量重复相同的代码,因为 CollectionBase 无法访问容器?
  • @amc 更新了答案以防止代码重复。这有点让 PointCollection 有点多余,但这会阻止大多数从 PixelCollection 到 PointCollection 的转换,反之亦然。如果您打算允许它们相互转换,那么您可以将 CollectionBase 和 PointCollection 一起折叠成一个类。
  • 太棒了,这正是我想要的。我想我没有意识到你可以继承一个模板类。谢谢!
【解决方案2】:

如果要检查point 对象是否也是pixel&lt;T&gt; 的类型,则可以简单地查看dynamic_cast 是否返回NULL。为了做到这一点,point 需要是多态的,所以向它添加一个虚拟析构函数。

这是一个例子:

point x(0, 0);
pixel<int> y(0, 0, 0);
point *pX = &x;
point *pY = &y;
if(dynamic_cast<pixel<int> *> (pX) != NULL) {
    std::cout << "x is a pixel<int>.";
}
if(dynamic_cast<pixel<int> *> (pY) != NULL) {
    std::cout << "y is a pixel<int>.";
}

输出如下:

y 是一个像素

您可以在coll 类中使用此代码来检查vector&lt;point *&gt; 的每个元素是一个点还是一个像素。但为了做到这一点,您需要知道正在存储的像素的特化(即它是pixel&lt;int&gt; 还是pixel&lt;float&gt;?)

coll 改为类模板可能更简单。

【讨论】:

    【解决方案3】:

    如果collectionpoints 和pixels 的处理基本相同,并且只包含其中一个,则将其设为模板类是有意义的。
    但是,对于 to_array,将其设为免费函数可能会更简单:

    template<class T> struct collection {
        std::vector<point<T> > data_;
        // ...
    };
    
    template<class T>
    void to_array(const collection<point<T> >& in, point<T>* out) {
        // ...
    }
    

    请注意,您必须提供一个公共接口来读取数据,或者至少有选择地授予to_array() 访问权限。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多