2016-09-28 2 views
0

ListAsSLLクラス(単独リンクリスト)を装飾してListAsDLLクラス(二重リンクリスト)を作成しました。今度はIteratorクラスを組み込み、ListAsDLLクラスを循環させたいと思います。次のように私のコードは次のとおりです。デコレータとイテレータのデザインパターンを使用してフレンドクラスを宣言する方法

#include <iostream> 
using namespace std; 

class ListAsSLL 
{ 
protected: 
    struct node{ 
     int i; 
     struct node* next; 
    }; 
    node* head; 
    node* tail; 
    int listSize; 

public: 
    ListAsSLL() 
    { 
     head = 0; 
     tail = 0; 
     listSize = 0; 
    } 
    virtual void addToBeginning(int i) 
    { 
     node * temp = new node; 
     temp->i = i; 
     if(head==0){ 
      temp->next = 0; 
      tail = temp; 
     }else if(head == tail) { 
      temp->next = tail; 
     } 
     else{ 
      temp->next = head; 
     } 
     head = temp; 
     listSize++; 
    } 
    virtual void print() 
    { 
     node* temp = head; 
     for (int i = 0; i < listSize; ++i) { 
      cout<<temp->i<<" "<<endl; 
      temp = temp->next; 
     } 
    } 
}; 

class Decorator : public ListAsSLL 
{ 
private: 
    ListAsSLL* list; 
public: 
    Decorator(ListAsSLL* l) 
    { 
     list = l; 
    } 
    virtual void addToBeginning(int i) 
    { 
     list->addToBeginning(i); 
    } 
    virtual void print() 
    { 
     list->print(); 
    } 
}; 

class PreviousDecorator : public Decorator 
{ 
protected: 
    struct dnode : public node 
    { 
     node* prev; 
    }; 
    dnode* head; 
    dnode* tail; 
    int listSize; 

public: 
    PreviousDecorator(ListAsSLL* l) : Decorator(l) 
    { 
     listSize = 0; 
     head = 0; 
     tail = 0; 
    } 
    virtual void addToBeginning(int i) 
    { 
     Decorator::addToBeginning(i); 
     dnode * temp = new dnode; 
     temp->i = i; 
     if(head==0){ 
      temp->next = 0; 
      tail = temp; 
     }else if(head == tail) { 
      temp->next = tail; 
      tail->prev = temp; 
     } 
     else{ 
      temp->next = head; 
      tail->prev = temp; 
     } 
     temp->prev = 0; 
     head = temp; 
     listSize++; 
    } 
    virtual void print() 
    { 
     Decorator::print(); 
     node* temp = head; 
     for (int i = 0; i < listSize; ++i) { 
      cout<<temp->i<<" "<<endl; 
      temp = temp->next; 
     } 
    } 
    friend class DLLIterator; 
}; 

class ListAsDLL : public ListAsSLL 
{ 
public: 
    virtual void addToBeginning(int i){} 
    virtual void print(){} 
}; 

class DLLIterator 
{ 
private: 
    ListAsDLL* dll; 
public: 
    DLLIterator(ListAsDLL* dll) 
    { 
     this->dll = dll; 
    } 
    int getFirst() 
    { 
     return dll->head->i; 
    } 
}; 

int main() { 
    ListAsSLL* dll = new PreviousDecorator(new ListAsDLL()); 
    dll->addToBeginning(20); 
    DLLIterator* it = new DLLIterator((ListAsDLL*) dll); 
    cout<<it->getFirst()<<endl; 

    delete dll; 
    delete it; 
    return 0; 
} 

唯一の問題は、私はイテレータクラスにパラメータとしてListAsDLLに渡していますので、私はそれが飾られているクラスの保護された属性にアクセスすることができませんということです。したがって、私はdll-> head-> iにアクセスすることはできません。

まず、デコレータデザインパターンを正しく使用していますか?次に、友人クラスが装飾されているクラスの保護属性にどのようにアクセスできますか。

+0

アクセスの質問については、 'ListAsDLL'クラスに' friend class DLLIterator; 'を追加することができます。 'class DLLIterator;'クラスは 'ListAsDLL'クラスの前に宣言されていなければなりません。 – Franck

+0

@Franck dll-> head-> iにアクセスしようとすると、まだセグメンテーション違反が発生します。これは実行時に追加されるだけなので、コンパイル時には存在しないと見なされるからです。 – Keagansed

+0

'ListAsSLL'が共通していても' PreviousDecorator * 'を' ListAsDLL * 'にキャストすることはできません。 'ListAsDLL'を読んだとき、未定義のフィールドを読み込んでいます。 – Franck

答えて

1

あなたのクラス階層がある:

ListAsSSL (a first head) <- Decorator <- PreviousDecorator (another head) 
    ^
    |---- ListAsDLL 

あなたは、彼らが共通して基本クラスを持っている場合でもListAsDLLPreviousDecoratorをキャストすることはできません。さらに、PreviousDecorator::addToBeginningメソッドでは、と書かれ、のままのListAsSSL::headではありません。

セルをカスタム化するには、ノードのタイプをクラスListAsSLLのレベルで開き、createEmptyNodeのような仮想メソッドを使用することができます。 ListAsDLLはこのメソッドをオーバーライドして、下のコードのように二重リンクノードを作成できます。

#include <iostream> 
using namespace std; 

class ListAsSLL 
{ 
protected: 
    struct node{ 
     int i; 
     struct node* next; 
    }; 
    node* head; 
    node* tail; 
    int listSize; 

public: 
    ListAsSLL() 
    { 
     head = 0; 
     tail = 0; 
     listSize = 0; 
    } 
    virtual node* createEmptyNode() const { return new node{}; } 
    virtual node* addToBeginning(int i) 
    { 
     node * temp = createEmptyNode(); 
     temp->i = i; 
     if(head==0){ 
      temp->next = 0; 
      tail = temp; 
     }else if(head == tail) { 
      temp->next = tail; 
     } 
     else{ 
      temp->next = head; 
     } 
     head = temp; 
     listSize++; 
     return temp; 
    } 
    virtual void print() 
    { 
     node* temp = head; 
     for (int i = 0; i < listSize; ++i) { 
      cout<<temp->i<<" "<<endl; 
      temp = temp->next; 
     } 
    } 
}; 

class ListAsDLL : public ListAsSLL 
{ 
protected: 
    struct dnode : public node 
    { 
     dnode* prev; 
    }; 
    virtual node* createEmptyNode() const { return new dnode{}; } 

public: 
    virtual node* addToBeginning(int i) 
    { node* result = ListAsSLL::addToBeginning(i); 
     static_cast<dnode*>(tail)->next = static_cast<dnode*>(result); 
     static_cast<dnode*>(result)->prev = static_cast<dnode*>(tail); 
    } 
    virtual void print(){} 
    friend class DLLIterator; 
}; 

class DLLIterator 
{ 
private: 
    ListAsDLL* dll; 
public: 
    DLLIterator(ListAsDLL* dll) 
    { 
     this->dll = dll; 
    } 
    int getFirst() 
    { 
     return dll->head->i; 
    } 
}; 

int main() { 
    ListAsSLL* dll = new ListAsDLL(); 
    dll->addToBeginning(20); 
    DLLIterator* it = new DLLIterator((ListAsDLL*) dll); 
    cout<<it->getFirst()<<endl; 

    delete dll; 
    delete it; 
    return 0; 
} 

次のコードでは、データの重複を避けるために新しい階層レベルのデコレータパターンを使用しています。 ListAsSLLは、単一リンクセルとダブルリンクセルを管理できる実装を表します。

新しいクラス階層は次のとおりです。

List <- ListAsSSL (implementation = head, tail) 
^
    |- Decorator (SLL) <- PreviousDecorator (DLL) 

私はクラスのための元の名前を保持しているが、あなたがそれらを変更することができます。

#include <iostream> 
#include <cassert> 
#include <memory> 
using namespace std; 

class List { 
    public: 
    virtual ~List() {} 
    virtual void addToBeginning(int i) {} 
    virtual void print() const {} 
    virtual int getFirst() const { assert(false); } 
}; 

class PreviousDecorator; 
class ListAsSLL : public List 
{ 
protected: 
    struct node{ 
     int i; 
     struct node* next; 

     node(int val) : i(val), next(nullptr) {} 
    }; 
    node* head; 
    node* tail; 
    int listSize; 
    friend class PreviousDecorator; 

public: 
    ListAsSLL() 
    { 
     head = 0; 
     tail = 0; 
     listSize = 0; 
    } 
    virtual ~ListAsSLL() 
     { node* cell = head; 
     for (int i=0; i<listSize; ++i) { 
      node* temp = cell->next; 
      delete cell; 
      cell = temp; 
     } 
     } 
    void addToBeginning(node* anode) 
    { 
     node * temp = anode; 
     if(head==0){ 
      temp->next = 0; 
      tail = temp; 
     }else if(head == tail) { 
      temp->next = tail; 
     } 
     else{ 
      temp->next = head; 
     } 
     head = temp; 
     listSize++; 
    } 
    virtual void addToBeginning(int i) { addToBeginning(new node(i)); } 
    virtual void print() const 
    { 
     node* temp = head; 
     for (int i = 0; i < listSize; ++i) { 
      cout<<temp->i<<" "<<endl; 
      temp = temp->next; 
     } 
    } 
    virtual int getFirst() const { assert(head); return head->i; } 
}; 

class Decorator : public List 
{ 
private: 
    std::unique_ptr<ListAsSLL> list; 
protected: 
    ListAsSLL& getImplementation() { return *list; } 
public: 
    Decorator(ListAsSLL* l) : list(l) {} 
    virtual void addToBeginning(int i) 
    { 
     list->addToBeginning(i); 
    } 
    virtual void print() const 
    { 
     list->print(); 
    } 
    virtual int getFirst() const { return list->getFirst(); } 
}; 

class DLLIterator; 
class PreviousDecorator : public Decorator 
{ 
protected: 
    struct dnode : public ListAsSLL::node 
    { 
     node* prev; 
     dnode(int val) : node(val), prev(nullptr) {} 
    }; 

public: 
    PreviousDecorator(ListAsSLL* l) : Decorator(l) {} 
    virtual void addToBeginning(int i) 
    { dnode* anode = new dnode(i); 
     getImplementation().addToBeginning(anode); 
     anode->prev = static_cast<dnode*>(getImplementation().tail); 
     getImplementation().tail->next = anode; 
    } 
    friend class DLLIterator; 
}; 

class DLLIterator 
{ 
private: 
    PreviousDecorator* dll; 
public: 
    DLLIterator(PreviousDecorator* dll) 
    { 
     this->dll = dll; 
    } 
    int getFirst() const 
    { 
     return dll->getFirst(); 
    } 
}; 

int main() { 
    PreviousDecorator* dll = new PreviousDecorator(new ListAsSLL()); 
    dll->addToBeginning(20); 
    cout<<dll->getFirst()<<endl; 

    delete dll; 
    return 0; 
} 
+0

@Keagansedこのソリューションはデコレータパターンを使用しません。私はこのようなパターンでもう一つ追加します。 – Franck

+0

さて、どうもありがとうございました。 – Keagansed

+0

@Keagansed 'ListAsDLL'クラスは、答えの最後の部分で削除されました。私はそれが 'PreviousDecorator'であるべきだと思います。 – Franck

関連する問題