2013-11-14 107 views
4

我想了解繼承方案中指針和模板之間的最佳解決方案。C++繼承:模板Vs指針

考慮以下類。

class Event 
{ 
}; 

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

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

每個用戶都可以擴展Event類和Filter類來容納實際的數據和實際的過濾函數。管道類只將過濾器與隊列連接起來並執行方法過程。

直到現在我總是用指針來處理繼承,例如, Filter指針的std :: vector以及接收Event指針的進程函數。而不是指針可以使用模板?

例如

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是基類集羣的擴展。但顯然它不起作用,所以爲了獲得一些靈活性,我不得不使用模板。

+0

'std :: vector '和'Filter'具有虛擬功能的事實並不能很好地結合在一起。 – dasblinkenlight

+0

所以std :: vector 是一個更好的選擇? – mariolpantunes

+0

是的。 Shooooooort – 2013-11-14 12:21:18

回答

3

實質上,您正在爲編譯時多態性交易運行時多態性。

這是什麼意思是用第二種方法,一個流水線只能由單一類型的過濾器組成,並且該類型必須在編譯時知道。第一種方法比這更靈活。

另一方面,內存管理在第二種方法中更簡單。但是,您可以使用智能指針與第一種方法來簡化事情。

此外,第二種方法可能更具性能。這是否相關是一個不同的問題。簡而言之,我會使用第一種方法,但會使用智能指針而不是原始指針。

+0

在這個特定的課程中,我對靈活性感興趣。 – mariolpantunes

+0

通常我使用普通指針,是一種在普通老C中編程的習慣。所以沒有明確的正確答案取決於問題。 – mariolpantunes

1

首先,我想使用模板將work.but你的代碼可以這樣寫:

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不僅事件,還包括其他類像事件1。您可以將T2設置爲Filter或其他類Filter1。

但是在這種情況下,這成爲一個缺點。您無法確定您的Filter類是否始終可以處理類Event的對象。其他類如Event1的對象也可以工作。

最後,我建議你在這種情況下使用指針而不是模板。

我希望這會幫助你。

+0

在模板定義中使用類時,是否必須給出基類的名稱? – mariolpantunes

+1

模板名稱完全是虛擬名稱,只是一個id。所以你不能給出基類的名字。 – yanchong

+0

那麼如何保證對象是某個基類的擴展? – mariolpantunes