2012-07-10 3 views
18

저는 C++에 비교적 익숙하지 않습니다.이 문제에 대한 답을 많이 찾았지만 결코 만족스러운 대답을 얻지 못했습니다.외부 클래스에 액세스하는 내부 클래스

내가 FSM이라는 구조를 가지고 있다고 가정 해 보겠습니다. 결국 내 코드에서 FSM의 여러 인스턴스를 만들 수 있습니다. FSM의 속성 중 하나는 int X이며 정적이 아니며 FSM의 모든 인스턴스는 X에 대해 고유 한 값을 가져야합니다.

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

내 질문은 :

struct FSM 
{ 
    public: 
    int x; 

    int getX(){return x;} 

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

이 다음과 같은 오류가 있습니다 :

이제 FSM의 특성 중 하나는 다음과 같이 X의 값을 읽을 필요가 또 다른 구조 submachine입니다 , 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(); 
} 

를 쓸 수 있는지 고려한다. OLI 말한대로

중 하나는 부모 FSM 객체에 submachine 객체 저장소의 참조를 가지고, 혹은 단지 (그것을 호출되는 방식을 명확하지 않다) 직접 onentryx의 값을 전달합니다. Boost.MSM docs 얼핏에서


나는 non-default-constructed submachines에이 쪽지를 발견했다.

꽤 못 생겼고, 백엔드를 여기에서 충분히 이해하지 못하고 리터럴 코드가 붙일 가치가있는 것은 아닙니다. 그 정확 경우, 당신은 당신의 외부 상태 머신 on_entry에 대한 포인터를 저장, 또는의 값을 추출 할 수 있습니다

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

:

또한 거기에서 링크 된 예제 코드는 다음과 같은 서명과 기관단총의 입력 방법을 보여줍니다 x 거기에 기록하고 그것을 기관에 기록하십시오.

+0

감사합니다. 이것은 내가 찾고 있던 것이고, 이제 실제로 얻습니다. OLI의 게시물이있는이 게시물은 나를 위해 그것을 만들었습니다. 나는 두 가지 대답을 모두 받아 들일 수 있기를 바란다. – Kam

관련 문제