2012-07-10 5 views
18

C++ 'ya göreceli olarak yeniyim ve bunun için bir cevap için çok şey aradım ama hiçbir zaman tatmin edici bir cevap almadım.Dış sınıftan erişen iç sınıf

FSM adlı bir yapımız olduğunu varsayalım. Sonunda kodumda, FSM çoklu örnekleri oluşturulabilir. FSM öğesinin özelliklerinden biri statik değil, FSM numaralı telefonun X için kendi değerine sahip olması gereken int X.

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

Sorum şu:

struct FSM 
{ 
    public: 
    int x; 

    int getX(){return x;} 

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

Bu aşağıdaki hata verir:

Şimdi FSM 'ın vasıflarından biri böyle X değerini okumak gerekiyor başka yapı submachine olduğunu , submachine, FSM'un bir üyesidir, bu nedenle FSM'un tüm özelliklerinin yerel örneklerine erişmesi gerekmiyor mu? Ve eğer değilse, bir FSM örneğini oluşturduğumuzda, tüm üyeleri yani submachine'un bir örneğini oluşturmuyor muyuz? Ve eğer öyleyse, o zaman neden onentry()'un ihtiyacı olan bir nesneyi yaratmamız gerekiyor?

Derleyicinin doğru olduğunu farz ediyorum, bu yüzden bu işi yapmak için bir yol olup olmadığını bilmek istiyorum.

Not: Ne yazık ki, bir olay çağrıldığında iç yapıların örnekleri (submachine) başlatılır ve bu nedenle yalnızca türünü tanımlayabilirim ve FSM içinde onlar için nesneleri başlatılamıyor.

cevap

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?

Hayır. Java'nın aksine, iç sınıf nesnelerinin bir dış nesneye dolaylı bir başvuru yoktur.

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

submachine bir tip değil, bir üye değişkendir.

struct FSM { 
    struct submachine { 
     ... 
    }; 

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

Ve üst nesne "görmek" için sm istiyorsanız, siz özellikle geçmeniz gerekir: Eğer üye değişkeni isteseydin, böyle bir şey yapmak zorundayız

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 
}; 

Aynı ilkenin, üye değişken olmayan submachine örnekleri için geçerli olduğunu unutmayın. Bir FSM örneğine erişebilmelerini istiyorsanız, birine bir başvuru göndermeniz gerekir.

Ayrıca bir başvuru kaynağı yerine bir işaretçi kullanabileceğinizi de unutmayın. Aslında, bir işaretçi birçok durumda daha fazla esneklik sunar.

+0

Ben başarmak istediğiniz başarmak için bir yol varsa? – Kam

+2

Downvoter: paylaşmaya özen gösteriliyor mu? –

+0

(Gecikme için üzgünüz, bağlantıyı buluyordum). İç içe sınıfları, bir parçası üyeleri ve [DR 45] (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45) 'ye bakınız başka üyeleri gibi, dış sınıf erişebilir 2003 yılından bu yana standart sorumu güncelledik –

2

struct submachine bildiriminin yalnızca tip; Aslında bu tür sınıfta bir alan oluşturmaz.

Aşağıdakilerden birini gerekir:

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

veya

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

Bu mysub alan yapar ve o zaman x erişmek istiyorum aynı şekilde erişmek.

submachine tanımı belirli bir X değere erişmek için fsm_->getX() ki böylece (o başlatmak için, örneğin bir işaretleme alanı FSM* ve submachine(FSM* fsm): fsm_(fsm) {} gibi muhtemelen bir kurucu) belirli bir FSM içermesi gerekir.

+0

Ne yazık ki, iç yapıların örnekleri çalışma zamanı (olaylar) olarak bildirilir ve böylece Ben sadece türü tanımlayabilirim ve onlar için nesneleri değil. – Kam

+2

Hala bir 'FSM' nesnesi olmayan' int g = getX(); 'yapamazsınız. Bu soruya nasıl cevap veriyor? –

1

Ben sadece ne yapmak istediğinizi bir tahmin yapıyorum ama benim tahminim doğru ise, aşağıda gibi bir şey düşünce olabilir.

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 yönlendirebilecek hiçbir FSM örneği olduğu yerde senin örnekte, yasal olarak serbest fonksiyonu

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

yazabilir düşünüyoruz. Oli söylediği gibi

Ya, üst FSM nesneye submachine nesne deposu, bir referans olması, ya da belki de, sadece (o çağrılan açık değildir) direkt olarak onentry içine x değerini geçmektedir. Boost.MSM docs hızlı bir bakışla itibaren


ben non-default-constructed submachines bu not buldum.

Oldukça çirkin

, yeterince arka ucu anlamıyorum buradan, tefsir ve edebi kod değerinde yapıştırma olmak izolasyon yeterli mantıklı olmayacaktır. bu doğru ise, kendi dış durum makinesi on_entry için bir işaretçi depolamak ya da değerini çıkarmak ya

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

:

orada da bağlantılı kod örneği aşağıdaki imza ile tali makinanın en giriş yöntemi gösterir x orada ve makinede kaydedin.

+0

Teşekkür ederiz! Aradığım şey buydu, şimdi anladım. OLI'nın yazı ile bu yazı benim için yaptı. Keşke her iki cevabı kabul edebilirim. – Kam