1

電話帳に似た C++ のアプリケーションで作業する必要があります。連絡先の STL リストを持つクラス Agenda です。連絡先階層に関しては、Contact という名前の基本クラス (抽象クラス) と、派生クラス Friend と Friend があります。知人(連絡先の種類)。

これらのクラスには、たとえば、連絡先の名前を返す getName という仮想メソッドがあります。

ここで、別の種類の連絡先である Company (Contact から派生) を追加して、 Composite パターンを実装する必要があります。これには、Contacts (STL リストも同様) のコレクションも含まれ、「leaf」タイプ (Friends または知人)、または会社でもかまいません。

したがって、Company は複合タイプです。

問題は、STL find_if を実装して、「リーフ」タイプの Contact と Company コレクション内の両方で (getName 関数を介して、またはその他の方法で) 特定の名前の連絡先を検索する方法と場所です。

言い換えれば、統一された関数定義を使用して、ツリーをトラバースして、一致する可能性のあるものを見つけるにはどうすればよいでしょうか?

私はかなり明確だったと思います...

4

3 に答える 3

2

まあ、それを行う1つの方法:

virtual contact* contact::findContact(std::string name)
{
    if(m_name == name) {return this;}
    return NULL;
}

それで:

contact * Company::findContact(std::string name)
{
    if(!contact::findContact(name) )
    {
        //For each contact in the contact list, findContact(name)
        //If we find something, return that.
        //Otherwise return null.
    }
    return this;
}

あなたがしていることは、ノードのタイプ (葉かそれ以外か) を気にせずに、探しているノードを見つけるように各ノードに要求することです。次に、各ノードが自身をチェックし、子ノードを持つノードの場合はその子をチェックします。

于 2010-04-26T18:48:13.623 に答える
1

最後の連絡先を検索したり、連絡先を検索したりするためのO(N)がある可能性があるため、リストは大きなタイプの連絡先には間違ったタイプです。
キーを使用してIDまたは名前で検索できるように、ハッシュマップ(boost / tr1のunordered_map)または通常のマップを使用することをお勧めします。
また、会社は単なる連絡先のツリーである必要があるように聞こえます。
ツリーの実装はここにあります
ツリーを移動して、必要なノードを見つけます。

于 2010-04-26T19:14:48.247 に答える
0

「ここで、別の種類の連絡先、Company (Contact から派生) を追加して、Composite パターンを実装する必要があります。これには、連絡先のコレクション (STL リストも) も含まれます。これは、「リーフ」タイプ (Friendsまたは知人)、または会社でもかまいません。」

Company の stl 互換の複合反復子を作成できます。

class Company : public Contact {
    std::list<Contact *> contactList;

    //snip...other private members
    friend class CompanyIterator;
    friend class ConstCompanyIterator;
  public:

     // nested iterator classes
     class CompanyIterator : public std::iterator<std::forward_iterator_tag, Contact *> {

          friend class Company;
          // pair<>.first is the iterator obtain by calling begin()
          // pair<>.second is the end iterator
          std::stack< std::pair< std::list<Contact *>::iterator, 
                      std::list<Contact *>::iterator> > iters_stack;

          Contact *pCurrentContact;
          Company *pCompany; // This is the top level company which will be iterated.

        public:

          explicit CompanyIterator(Company &c);

          // Required forward iterator methods follow
          CompanyIterator();
          CompanyIterator(const CompanyIterator&);
          CompanyIterator& operator=(const CompanyIterator& other);
          Contact &operator*() const;
          Contact *operator->() const;
          CompanyIterator& operator++();
          CompanyIterator operator++(int);

          bool operator==(const CompanyIterator& x) const;
          bool operator!=(const CompanyIterator& x) const;
     };

     // nested iterator class
     class ConstCompanyIterator : public std::iterator<std::forward_iterator_tag, 
          const Contact *> {

          friend class Company;
          // We use CompanyIterator to implement ConstCompanyIteraor  
           CompanyIterator inner_iter; // fwd operations here,
                                      // using "const_cast<Company *>(this)->method()"
        public:

          explicit ConstCompanyIterator(const Company & dir);

          // This ctor will function as a cast operator, to convert a CompanyIterator
          // into a ConstCompanyIterator
          ConstCompanyIterator(const CompanyIterator &iter);

          // Required forward iterator methods follow
          ConstCompanyIterator();
          ConstCompanyIterator(const ConstCompanyIterator&);
          ConstCompanyIterator& operator=(const ConstCompanyIterator& other);

          const Contact &operator*() const;
          const Contact *operator->() const;

          ConstCompanyIterator& operator++();
          ConstCompanyIterator operator++(int);

          bool operator==(const ConstCompanyIterator& x) const;
          bool operator!=(const ConstCompanyIterator& x) const;
     };

    typedef CompanyIterator iterator;
    typedef ConstCompanyIterator const_iterator;

    iterator begin();
    iterator end();

    const_iterator begin() const;
    const_iterator end() const;

    // snip... other Company public methods
};

上記の前方反復子メソッドの実装については、Github の複合反復子コードを参照してください。実装のほとんどは Directory.cpp にあります。github コードは、ファイル システムをモデル化する複合パターン用です。Class Directory はコンポジットです。クラス ファイルはリーフ クラスです。Class Node は基本コンポーネント クラスです。

find_if のファンクタは次のようになります

 FindIfFunctor {
      std::string name;
    public:
     FindIfFunctor(const std::string& n) : name(n) {} 
     bool operator()(const Contact& c) { return c.getName().compare(name); }
 }; 

最後に、find_if コード

 Company c;
 // snip... stuff gets added to company
 string someName("IBM");

 find_if(c.begin(), c.end(), FindIfFunctor(someName));
于 2014-01-07T19:06:22.853 に答える