3

次のような階層があります。

         class Element{ public : virtual void Accept(Visitor&) = 0
                 protected : Element();   int num;
          };

         class ElementA : public Element{
                 public : ElementA(); 
                 void Accept(Visitor& v) {v.Visit(this};}
         };

         class ElementB : public Element{
                 public : ElementB(); 
                 void Accept(Visitor& v) {v.Visit(this};}


         class Visitor{
                 public: void Visit(ElementA*);
                 void Visit(ElementB*);
         };

編集: num の値を提供する階層にメソッド int getNum() を追加する必要があります。ただし、これには階層全体を再度コンパイルする必要があり、それは許可されていません。したがって、階層の再コンパイルが不要になるように、階層の設計を変更する必要があります。

4

4 に答える 4

3

あなたがやりたいことは、きれいに設計された方法では不可能です。その階層の完全な再コンパイルがなぜこのような問題になるのかはわかりませんがreinterpret_cast、アクセス保護を取り除くなどの UB ハックを使用せずに技術的に可能な解決策があります。

int Visitor::getNum(Element* pe)
{ 
  //define a pick-pocket... ;)
  struct ElementNumAccessor : private Element
  {
    ElementNumAccessor(Element const& e) : Element(e) {}   
    int getNum() { return num; }

    void Accept(Visitor&); //has to be declared, but needs not be defined
  };

  //...and let him work:
  ElementNumAccessor ea(*pe);
  return ea.getNum();
}

この魂の動き: http://ideone.com/e1chSX
これは、保護されたアクセスが推移的であるという事実を悪用しますが、num が必要な各要素のコピーを犠牲にします。構造体を関数のローカル クラスにしたので、他の目的で実際に使用するというアイデアは誰も得られませんでした。

ただし、この手法はハックであり、このように使用することを意図していない言語機能の悪用であることに注意してください。

私のアドバイスは次のとおりです。階層がプログラムに非常に絡み合っていて、それを変更すると再コンパイルの恐怖が残る場合は、プログラムをリファクタリングしてコンパイル時の依存関係を減らし、必要な変更を行う時が来ました。

于 2013-04-05T06:58:54.720 に答える
0

GetNumVisitor1 つの可能性は、をフレンドとして宣言し、メンバー変数に直接Element classアクセスすることです。次に、値を返すnumメソッドを に追加します。GetNumVisitor

class Element { 
  ...
  friend GetNumVisitor;  // declare GetNumVisitor as a friend class
  ...
};

GetNumVisitor : public Visitor {
 private: 
  int  m_numelement;
 public : 
  void visit(Element *E) { m_elementNum = E->num; }
  int getNum() const { return m_elementNum;}
};

あなたはそれを次のように呼び出す必要があります

 ElementA element_a();
 ElementB element_b();
 GetNumVisitor getnumVisitor();
 element_a.accept(getnumVisitor);
 int a = getnumVisitor.getNum();
 element_b.accept(getNumVisitor);
 int b = getnumVisitor.getNum();
 ...
于 2013-04-05T06:16:41.037 に答える