5

継承シナリオでのポインターとテンプレートの間の最適なソリューションは何かを理解しようとしています。

次のクラスを検討してください。

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 の拡張であることを理解できると思いました。しかし、どうやらうまくいかないので、ある程度の柔軟性を得るために、テンプレートを使用する必要がありました。

4

2 に答える 2

3

本質的に、実行時のポリモーフィズムをコンパイル時のポリモーフィズムと交換しています。

これが意味することは、2 番目のアプローチでは、パイプラインは 1 つのタイプのフィルターのみで構成でき、そのタイプはコンパイル時に認識されている必要があるということです。最初のアプローチはそれよりも柔軟です。

一方、メモリ管理は 2 番目の方法の方が簡単です。ただし、最初のアプローチでスマート ポインターを使用して、物事を単純化することができます。

さらに、2 番目のアプローチの方がパフォーマンスが向上する可能性があります。これが関連するかどうかは別の問題です。

簡単に言えば、最初のアプローチを使用しますが、生のポインターの代わりにスマート ポインターを使用します。

于 2013-11-14T12:15:37.477 に答える
1

まず、テンプレートを使用するとうまくいくと思いますが、コードは次のように記述できます。

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 として設定できます。

しかし、この状態ではこれが不利になります。Filter クラスが常にクラス Event のオブジェクトを処理できるかどうかを確認することはできません。Event1 のオブジェクトなど、他のクラスも機能します。

最後に、この状態ではテンプレートではなくポインターを使用することをお勧めします。

これがお役に立てば幸いです。

于 2013-11-14T12:21:49.000 に答える