2017-03-23 2 views
0

私は基本クラスと2つの派生クラスを持っています。今、私は基本クラスのベクトルを作成したいと思います。新しい要素を追加すると、新しい要素のどのクラスがチェックされます。しかし、C++では、instanceOfのような機能がないので、変数typeを追加してチェックする必要があります。ここに私のコードがあります。Distinc由来クラスC++

class Element { 
public: 
    int type; 
    int getIndex() const { 
     return index; 
    } 

    void setIndex(int index) { 
     this->index = index; 
    } 

    const std::string& getMsg() const { 
     return msg; 
    } 

    void setMsg(const std::string& msg) { 
     this->msg = msg; 
    } 

    std::string toString() { 
     std::stringstream sbuf; 
     sbuf << "index: " << index << "\n"; 
     sbuf << "Message: " << msg << "\n"; 
     return sbuf.str(); 
    } 

private: 
    int index; 

    std::string msg; 

}; 

2つの派生クラス:別のクラスにおいて

class This: public Element { 
public: 
    This():Element(1){} 
    ~This(); 

    const std::vector<std::string>& getArguments() const { 
     return arguments; 
    } 

    void setArguments(const std::vector<std::string>& arguments) { 
     this->arguments = arguments; 
    } 

    void add(std::string value) { 
     arguments.push_back(value); 
    } 

private: 
    std::vector<std::string> arguments; 


}; 

class That: public Element { 
public: 
    That():Element(2){} 
    ~That(); 

    const std::string& getThatVal() const { 
     return thatVal; 
    } 

    void setThatVal(const std::string& thatVal) { 
     this->thatVal = thatVal; 
    } 

private: 
    std::string thatVal; 


}; 

、私は要素の配列を作成します。

class Visitor { 
private: 
    int numOfThis = 0; 
    int numOfThat = 0; 
    std::vector<Element> vecEle; 

public: 
    void add(Element ele) { 
     vecEle.push_back(ele); 
     if (ele.type == 1) { 
      numOfThis++; 
     } else if (ele.type == 2) { 
      numOfThat++; 
     } 
    } 

    int getNumOfThat() const { 
     return numOfThat; 
    } 

    int getNumOfThis() const { 
     return numOfThis; 
    } 
}; 

私の質問はこれをどのように処理するかです。この状況のた​​めのデザインパターンはありますか?感謝

+2

C++に 'instanceof'があっても、あなたのクラスが多態性ではないので、ここでは動作しません。それについて学び、ベクトルの基底へのポインタを格納します。 'dynamic_cast'を試してみると、それぞれの要素の型が分かります。 – DeiDei

+0

オブジェクトの種類に応じて切り替える必要がある場合...設計上の問題があります。オブジェクトを常に適切に使用します。リストの項目をキャストしたい場合は、より具体的なタイプにする場合は、下位レベルの抽象化のレバーにしたいと考えています。コード匂いと呼ばれています。この臭いが消えるデザインパターンがたくさんあります。このテーマのいくつかの本を読んでください。 –

答えて

4

あなたは、ベクター内のポインタではなく、オブジェクトを格納することができ、:

std::vector<Element *> vecEle; 

はその後、派生クラスがあなたのポインタの型であるかを決定するためにdynamic_castを使用することができます。

// dynamic_cast will try to convert pointer of base class to derived class, 
// and return NULL on fail 
Element *pElem= vecEle[0]; // you can traverse your vector if needed 
if (This *pThis = dynamic_cast<This *>(pElem)) { 
    // object is This type 
} else if (That *pThat = dynamic_cast<That *>(pElem)) { 
    // object is That type 
} 
1

クラス要素が すなわちVisitElement(Visitor* visitor)呼ばれる純粋仮想関数を含む基底クラスであるべきです。

Visitorクラスは、コードで記述したクラスとはまったく関係なく、実際にはVisitorというデザインパターンとして実装されています。これは、オーバーロードされた関数このビジタークラスもint counterThisint counterThatが含まれています

void Visit(This* thisElem) {thisElem->VisitElement(this)}

void Visit(That* thatElem){thatElem->VisitElement(this)}

を含むことを意味します。クラスこれでVisitElementのための実装はVisitElemntのための実装が

VisitElement (Visitor* visitor){ visitor->counterThat++;}

そして最後に、実際に必要にカウントするために、と同じくらい簡単であること

クラスで

VisitElement(Visitor* visitor){ visitor->counterThis++;}

のと同じくらい簡単です基本クラスの要素ポインタのベクトルと、ベクトル呼び出しvisitor->Visit(elemFromBector)に含まれる各ポインタにループします。ループが終了すると、必要な2つのintのビジターオブジェクトをクエリできます。 このソリューションには、多形性と訪問者のデザインパターン、および元のコードで見逃したようなカプセル化原則が含まれています。

dynamic_castを使用しないでください。不十分です。プロダクションコードに含めないでください。 dynamic_castが必要だと思えば、コードに何か問題があるので再度考えてみてください。 お勧めのアドバイス多型封筒ビジターデザインパターンを読んで、私のロジックを非常に簡単に理解できるはずです。

+0

編集のおかげで、私は自分のセルからやっていて、それに苦労しました。 – Calin

+0

ここに訪問者パターンは必要ありません。 "すべきか"というのはあまりにもストリングです。 – ROX

関連する問題