12

私は Java の世界から来て、現在小さな C++ プログラムを作成しています。いくつかの作業を行い、作業の結果をリストとして返すオブジェクトがあります。

1日後、コンテナ内での重複を避けるために、結果をセットに保存するようにオブジェクトの動作を変更しました。しかし、初めてインターフェイスにリストを使用したため、単純にセットを返すことはできません。オブジェクトのインターフェイスを指定し、内部で使用するコンテナーの種類を忘れるために使用できる共通のコンテナー インターフェイスはありますか?

現時点では、すべての値を追加するセットを作成し、セットからリストを作成しています:

return std::list<foo>(this->mySet.begin(), this->mySet.end())

少し奇妙に思えます。

4

4 に答える 4

13

コンテナーの概念は、イテレーターによって具現化されます。
これまで見てきたように、特定のタイプのコンテナーをハードコーディングすることは、おそらくあなたが望むものではありません。したがって、クラスがイテレータを返すようにします。その後、conatiners イテレーターを再利用できます。

class MyClass
{
    private:
        typedef  std::list<int>            Container;
    public:
        typedef  Container::iterator       iterator;
        typedef  Container::const_iterator const_iterator; 


        iterator        begin()        {return myData.begin();}
        const_iterator  begin() const  {return myData.begin();}

        iterator        end()          {return myData.end();}
        const_iterator  end()   const  {return myData.end();}

    private:
        Container   myData;
};

Container タイプを std::list から std::set に変更するとき、誰も知る必要はありません。
また、他のコンテナが使用する標準名を使用することで、クラスが STL の他のコンテナのように見えるようになります。

注: const_iterator を返すメソッドは、const メソッドである必要があります。

于 2009-06-29T19:25:00.940 に答える
12

コンテナーを含む C++ 標準ライブラリ全体は、Java とは異なり、インターフェイス (継承、ポリモーフィズム) ではなく、テンプレートベース (効率のため) です。

コレクションの周りにポリモーフィック ラッパーを作成することもできますが、これは C++ の方法ではありません。

最も簡単な解決策は、いくつかの型エイリアスを使用してプログラムを単純化することです。

#include <iostream>
#include <list>
#include <vector>

using namespace std;

class Test {

private:
    typedef vector<int> Collection;

    Collection c;

public:

    typedef Collection::const_iterator It;

    void insert(int Item) {
        c.push_back(Item);
    }

    It begin() const { return c.begin(); }
    It end()   const { return c.end(); }

};

int main() {

    Test foo;

    foo.insert(23);
    foo.insert(40);

    for (Test::It i = foo.begin(); i != foo.end(); ++i)
        cout << *i << endl;

    return 0;
}

Collection他に何も変更せずに -typedef を変更できるようになりました。(注:Collection公開すると、明示的に使用した型をユーザーが参照できるようになります)

于 2009-06-29T19:06:19.743 に答える
3

インターフェイスが存在しません。代わりに、通常はテンプレートを使用し、単純に「コンテナーとして動作する限り、型は気にしません」と言うだけです。

関数が次のようになっていると仮定します。

std::list<int> DoStuff()

次のように呼び出すことができます。

template <typename container_type>
void caller() {
  container_type result = DoStuff();
}

代わりに a を返す場合は、最初の関数だけを変更する必要がありますset。呼び出し元の関数はあまり気にしません (もちろん、リストの詳細に依存しない限り)。

もう少しサンプル コードを投稿していただければ、C++ での実行方法をより適切に提案できる可能性があります。

于 2009-06-29T19:17:17.240 に答える
2

あなたの説明から、短い答えはノーだと思います。

一般に、このような形式のコレクションを作成するときは、通常、使用しているコンテナーを指定するために typedef を使用します。

class Object {
   typedef std::list<int> Cont;
   typedef Cont::iterator iterator;
   typedef Cont::const_iterator const_iterator;

   // ....
};

すべてのクライアント コードは「Object::Cont」などを参照するため、クライアントがコンテナの一般的な機能のみを使用する限り、コンテナが変更されても変更する必要はありません。

API を今変更できない場合は、ソリューションはかなり良いと思いますが、持っているデータによっては、一意になりがちな挿入をたくさん行う場合は、引き続き API を使用する方が効率的かもしれません。リストを作成し、最後の重複のみを削除します。

void foo (std::list<int> & list) {

  // ... fill the list

  list.sort ();
  list.unique (); 
}
于 2009-06-29T19:16:57.710 に答える