2012-07-10 22 views
18

私はC++には比較的新しいので、私はこのことに対する答えをたくさん見てきましたが、満足のいく回答は得られませんでした。外部クラスにアクセスする内部クラス

私はFSMという構造を持っているとしましょう。最終的に私のコードでは、FSMの複数のインスタンスを作成することができます。 FSMの属性のうち1つはint Xです。これは静的ではなく、FSMのすべてのインスタンスはXの独自の値を持つ必要があります。

は今、FSMの属性の一つは、このようなXの値を読み込む必要がある別の構造体submachineです:

struct FSM 
{ 
    public: 
    int x; 

    int getX(){return x;} 

    struct submachine 
    { 
     void onentry() {int g = getX();}; 
    }; 
}; 

これは、次のエラーを与える:

Error: 'FSM::getX' : illegal call of non-static member function

私の質問は、submachineFSMのメンバーなので、すべての属性のローカルインスタンスにはアクセスしないでください。FSM?そうでない場合は、FSMというインスタンスを作成すると、すべてのメンバーのインスタンス、つまりsubmachineが作成されませんか?もしそうなら、なぜonentry()に必要なオブジェクトを作成する必要がありますか?

私はコンパイラが正しいと仮定しているので、この作業を行う方法があるかどうかも知りたいと思うでしょう。

注:残念ながら、内部構造のインスタンス(submachine)は、イベントが呼び出されたときにインスタンス化されるため、型の定義のみが可能で、FSMのオブジェクトのインスタンス化はできません。

答えて

34

my question is, submachine is a member of FSM, so it should have access to local instances of all the attributes of FSM, no?

いいえ。Javaとは異なり、内部クラスオブジェクトは外部オブジェクトへの暗黙の参照を持ちません。

wouldn't we be creating an intance of all its members i.e. submachine?

submachineタイプなく、メンバ変数です。

struct FSM { 
    struct submachine { 
     ... 
    }; 

    submachine sm; // Member variable of type submchine 
}; 

をそして、あなたはその親オブジェクトを「見る」ことsmをしたい場合は、明示的にそれを渡す必要があります:あなたはメンバ変数を望んでいた場合、あなたはこのような何かをする必要があると思います

struct FSM { 
    struct submachine { 
     FSM &parent; // Reference to parent 
     submachine(FSM &f) : parent(f) {} // Initialise reference in constructor 
    }; 

    submachine sm; 

    FSM() : sm(*this) {} // Pass reference to ourself when initialising sm 
}; 

メンバ変数でないsubmachineのインスタンスにも同じ原則が適用されることに注意してください。 FSMインスタンスにアクセスできるようにするには、参照を渡す必要があります。

参照ではなくポインタを使用できることにも注意してください。実際、ポインタは多くの場合、より大きな柔軟性を提供します。

+0

もし私が達成したいことを達成する方法があれば? – Kam

+2

Downvoter:気にする? –

+0

(遅れて申し訳ありませんが、リンクを見つけることができました)。ネストされたクラスはメンバーであり、他のメンバーと同様に外部クラスにアクセスできます。[DR 45](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45)の2003年以来の標準 –

2

struct submachineと宣言すると、タイプがと定義されています。実際にその型のクラスにフィールドを作成するわけではありません。

次のいずれかが必要になります

struct submachine mysub; // creates a field after the class is defined 

または

struct submachine 
{ 
    . . . 
} mysub; // creates the field "mysub" also, as the structure is being defined 

これはmysubフィールドを作り、そしてあなたは、あなたがxにアクセスしたいのと同じ方法でそれにアクセスします。

submachineの定義は、特定のX値にアクセスするためにfsm_->getX()を言うことができるように、(それを初期化するために、例えばポインタフィールドFSM*、およびsubmachine(FSM* fsm): fsm_(fsm) {}のような、おそらくコンストラクタ)特定FSMを含める必要があります。

+0

残念ながら、内部構造のインスタンスはランタイム(イベント)として宣言されています私は型を定義することしかできず、型をインスタンス化しません。 – Kam

+2

あなたはまだ 'int g = getX();'を 'FSM'オブジェクトなしで使うことはできません。これはどのように質問に答えますか? –

1

私はあなたがしたいことを推測していますが、私の推測が正しいとすれば、あなたは以下のようなものを考えるかもしれません。

struct FSM_Base { 
    int x; 

    struct submachine1; 
    struct submachine2; 

    FSM_Base() : x(0) {} 
    virtual ~FSM_Base() {} 
}; 

struct FSM_Base::submachine1 : virtual public FSM_Base { 
    void oneentry() { int g = x; } 
}; 

struct FSM_Base::submachine2 : virtual public FSM_Base { 
    void oneentry() { int g = x; } 
}; 

struct FSM : public FSM_Base::submachine1, 
      public FSM_Base::submachine2 { 
    FSM_Base::submachine1 * sub1() { return this; } 
    FSM_Base::submachine2 * sub2() { return this; } 
}; 
3

subが参照できることを FSMインスタンスが存在しないところあなたの例では、私は合法的にフリー機能

void foo() 
{ 
    FSM::submachine sub; 
    sub.onentry(); 
} 

を書くことができると考えています。オリが言うよう

のいずれかが、その親FSMオブジェクトにsubmachineオブジェクトストアの参照を持っている、または多分だけ(呼び出される方法は明らかではない)を直接onentryxの値を渡します。


私はnon-default-constructed submachinesにこのノートを見つけBoost.MSM docsで簡単に見から。

これはかなり醜いですが、私はここでそれを言い換えれば十分理解できません。文字通りのコードは貼り付ける価値があるほど孤立していません。

そこからリンクされているサンプルコードは、以下の署名でサブマシンの入力方法を示しています

template <class Event,class FSM> void on_entry(Event const&,FSM&); 

それが正確だ場合、あなたは外ステートマシンon_entryへのポインタを格納し、またはの値を抽出しますか、そこにxを入れ、それをサブマシンに記録する。

+0

ありがとうございます!これは私が探していたものですが、今は実際にそれを手に入れます。 OLIのポストとこのポストは私のためにそれを作った。私は両方の答えを受け入れることができたらいいと思う。 – Kam

関連する問題