Внутренний класс, доступ к внешнему классу
Я относительно новичок в С++, и я много искал ответа для этой вещи, но у меня не было удовлетворительного ответа.
Скажем, у меня есть структура, называемая FSM
. В конечном итоге в моем коде можно создать несколько экземпляров FSM
. Одним из атрибутов FSM
является int X
, который не является статическим, каждый экземпляр FSM
должен иметь собственное значение для X
.
Теперь одним из атрибутов FSM
является другая структура submachine
, которая должна читать значение X
следующим образом:
struct FSM
{
public:
int x;
int getX(){return x;}
struct submachine
{
void onentry() {int g = getX();};
};
};
Это приводит к следующей ошибке:
Ошибка: "FSM:: getX": незаконный вызов нестатической функции-члена
Мой вопрос: submachine
является членом FSM
, поэтому не должен ли он иметь доступ к локальным экземплярам всех атрибутов FSM
? А если нет, когда мы создадим экземпляр FSM
, не будем ли мы создавать экземпляр всех его членов, т.е. submachine
? И если да, то почему нам нужно создать объект, который нужен onentry()
?
Я предполагаю, что компилятор прав, поэтому я также хотел бы знать, есть ли способ сделать эту работу.
ПРИМЕЧАНИЕ. К сожалению, экземпляры внутренних структур (submachine
) создаются при вызове события и поэтому я могу определить тип, а не создавать объекты для них в FSM
.
Ответы
Ответ 1
Мой вопрос: автомат является членом FSM, поэтому он должен иметь доступ к локальным экземплярам всех атрибутов FSM, no?
Нет. В отличие от Java, внутренние объекты класса не имеют неявной ссылки на внешний объект.
не будем ли мы создавать интонацию всех его членов, то есть автомата?
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
, вам нужно передать ссылку на него.
Обратите внимание, что вы можете использовать указатель вместо ссылки. Фактически, во многих случаях указатель обеспечивает большую гибкость.
Ответ 2
считают, что в вашем примере я могу законно написать бесплатную функцию
void foo()
{
FSM::submachine sub;
sub.onentry();
}
где нет экземпляра FSM, к которому может обращаться sub
.
Либо, как говорит Оли, объект submachine
хранит ссылку на свой родительский объект FSM
или может просто передать значение x
непосредственно в onentry
(неясно, как это получается вызывается).
С быстрым просмотром Boost.MSM docs я нашел эту заметку на нестандартные автоматы.
Это довольно уродливо, я не понимаю, что такое backend достаточно, чтобы перефразировать его здесь, и буквальный код не будет иметь достаточного смысла в изоляции, чтобы его можно было вставлять.
Приведенный здесь примерный код также показывает способ ввода в автомат со следующей сигнатурой:
template <class Event,class FSM> void on_entry(Event const&,FSM& );
если это точно, вы можете либо сохранить указатель на свой внешний конечный автомат on_entry
, либо извлечь значение x там и записать его в автомат.
Ответ 3
Обратите внимание, что объявление 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
должно быть указано конкретное FSM
(например, поле указателя FSM*
и, возможно, конструктор типа submachine(FSM* fsm): fsm_(fsm) {}
для его инициализации), чтобы вы могли сказать fsm_->getX()
для доступа к определенному x
значение.
Ответ 4
Я только догадываюсь о том, что вы хотите сделать, но если мое предположение верно, вы можете подумать о чем-то вроде ниже.
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; }
};