【问题标题】:C++ inheritance: Templates Vs PointersC++ 继承:模板与指针
【发布时间】:2013-11-14 12:07:28
【问题描述】:

我试图了解在继承场景中指针和模板之间的最佳解决方案是什么。

考虑以下类。

class Event
{
};

class Filter
{
    public:
        virtual void process(Event *event) = 0;
};

class Pipeline
{
    private:
        std::vector<Filter*> _filters
};

每个用户都可以扩展 Event 类和 Filter 类来保存实际数据和实际过滤功能。管道类只是将过滤器和队列连接在一起,执行方法流程。

直到现在我一直使用指针来处理继承,例如过滤器指针的 std::vector 和接收事件指针的过程函数。可以用模板代替指针吗?

例如

class Event
{
};

template<class Event> class Filter
{
    public:
        virtual void process(Event *event) = 0;
};

template<class Filer> class Pipeline
{
    private:
        std::vector<Filter> _filters
};

这是否可行,甚至可能,主要含义是什么?

我还有一个例子要讨论。 考虑以下代码:

template<class Element, class Cluster>
Cluster* closestCluster(Element *e, std::vector<Cluster*> &clusters)
{
    double minDist = clusters[0]->distance(e);
    Cluster *c = clusters[0];
    for(std::size_t i = 1 ; i < clusters.size(); ++i)
    {
         double tmp = clusters[i]->distance(e);
         if(tmp < minDist)
         {
             minDist = tmp;
             c=clusters[i];
         }
    }
    return c;
}

Cluster* closestCluster(Element *e, std::vector<Cluster*> & clusters)
{
    double minDist = clusters[0]->distance(e);
    Cluster *c = clusters[0];
    for(std::size_t i = 1 ; i < clusters.size(); ++i)
    {
        double tmp = clusters[i]->distance(e);
        if(tmp < minDist)
        {
            minDist = tmp;
            c=clusters[i];
        }
     }
     return c;
}

乍一看,我看这个功能并没有什么大的区别。 但在我的代码中,只有第一个有效。因为我的集群数组属于这种类型:

std::vector<KMedoidCluster*> &clusters

我以为编译器可以理解 KMedoidclsuter 是基类 Cluster 的扩展。但显然它不起作用,所以为了获得一些灵活性,我不得不使用模板。

【问题讨论】:

  • std::vector&lt;Filter&gt;Filter 具有虚函数的事实不能很好地结合在一起。
  • 那么 std::vector 是更好的选择吗?
  • 我只是想掌握模板的优点以及何时使用它

标签: c++ templates pointers inheritance


【解决方案1】:

本质上,您是在用运行时多态性换取编译时多态性。

这意味着对于第二种方法,管道只能包含一种类型的过滤器,并且必须在编译时知道该类型。第一种方法比这更灵活。

另一方面,第二种方法的内存管理更简单。但是,您可以在第一种方法中使用智能指针来简化事情。

此外,第二种方法可能更高效。这是否相关是另一个问题。

简而言之,我会使用第一种方法,但会使用智能指针而不是原始指针。

【讨论】:

  • 在这个特定的课程中,我对灵活性很感兴趣。
  • 我通常使用普通指针,是用普通老C编程的习惯。所以没有明确的正确答案取决于问题。
【解决方案2】:

首先我认为使用模板会起作用。但是您的代码可能会这样写:

class Event
{
};

template<class T1> class Filter
{
    public:
        virtual void process(T1 *event) = 0;
};

 template<class T2> class Pipeline
{
    private:
        std::vector<T2> _filters
};

使用模板的主要优点是,您可以设置 T1 类,不仅是 Event,还可以设置其他类,如 Event1。您可以将 T2 设置为 Filter 或其他类 Filter1。

但是在这种情况下,这将成为一个劣势。您不能确保您的过滤器类总是可以处理类事件的对象。其他类如 Event1 的对象也可以工作。

最后,我建议你在这种情况下使用指针而不是模板。

我希望这会对你有所帮助。

【讨论】:

  • 在模板定义中使用类时,是不是必须给出基类的名称?
  • 模板名称完全是一个虚拟名称,只是一个id。所以不能给出基类的名字。
  • 那么如何保证对象是某个基类的扩展呢?
  • 你可以这样写:BaseClass *base_class.
  • 你能给我举个例子吗?
猜你喜欢
  • 2013-01-02
  • 1970-01-01
  • 2011-02-11
  • 2017-10-20
  • 1970-01-01
  • 1970-01-01
  • 2011-04-17
  • 1970-01-01
  • 2013-06-13
相关资源
最近更新 更多