我对C ++比较陌生,我已经看了很多答案,但我从来没有得到满意的答案。
假设我有一个名为FSM
的结构。最终,在我的代码中,可以创建多个FSM
实例。 FSM
的{{1}}属性之一不是静态的,int X
的每个实例都应该有FSM
的值。
现在,X
的一个属性是另一个结构FSM
,需要像这样读取submachine
的值:
X
这会出现以下错误:
错误:'FSM :: getX':非静态成员函数的非法调用
我的问题是,struct FSM
{
public:
int x;
int getX(){return x;}
struct submachine
{
void onentry() {int g = getX();};
};
};
是submachine
的成员,所以它不应该访问FSM
所有属性的本地实例吗?如果没有,当我们创建FSM
的实例时,我们不会创建其所有成员的实例,即FSM
吗?如果是这样,那么为什么我们需要创建一个submachine
需要的对象?
我假设编译器是正确的,所以我也想知道是否有办法使这项工作。
注意:不幸的是,内部结构(onentry()
)的实例在调用事件时被实例化,因此我只能定义类型,而不是在submachine
中为它们实例化对象。 / p>
答案 0 :(得分:35)
我的问题是,submachine是FSM的成员,所以它应该可以访问FSM所有属性的本地实例,不是吗?
没有。与Java不同,内部类对象没有对外部对象的隐式引用。
我们不会创建其所有成员(即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
实例,则需要将引用传递给其中一个。
另请注意,您可以使用指针而不是引用。实际上,指针在许多情况下提供了更大的灵活性。
答案 1 :(得分:3)
考虑到在你的例子中,我可以合法地编写一个自由函数
void foo()
{
FSM::submachine sub;
sub.onentry();
}
{em}没有 sub
可以引用的FSM实例。
正如Oli所说,让submachine
对象存储对其父FSM
个对象的引用,或者只是将x
的值直接传递给onentry
(目前尚不清楚它是如何被调用的。)
快速查看Boost.MSM docs我在non-default-constructed submachines上找到了这个说明。
这很丑陋,我不明白后端足以在这里解释它,文字代码在孤立中没有足够的意义值得粘贴。
从那里链接的示例代码还显示了具有以下签名的子机器的输入方法:
template <class Event,class FSM> void on_entry(Event const&,FSM& );
如果这是准确的,您可以存储指向外部状态机on_entry
的指针,或者在那里提取x的值并将其记录在子机中。
答案 2 :(得分: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
的定义需要包含一个特定的FSM
(例如指针字段FSM*
,可能还有像submachine(FSM* fsm): fsm_(fsm) {}
这样的构造函数来初始化它),这样你就可以了说fsm_->getX()
可以访问某个X
值。
答案 3 :(得分: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; }
};