内部类访问外部类

时间:2012-07-10 00:24:25

标签: c++ structure

我对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>

4 个答案:

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