C++ 内部类访问外部类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11405069/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:07:09  来源:igfitidea点击:

Inner class accessing outer class

c++structure

提问by Kam

I am relatively new to C++, and I have looked a lot for an answer for this thing but I never got a satisfying answer.

我对 C++ 比较陌生,我已经寻找了很多关于这件事的答案,但我从来没有得到满意的答案。

Let's say I have a structure called FSM. Eventually in my code, multiple instances of FSMcan be created. One of FSM's attributes is int Xwhich is not static, every instance of FSMshould have its own value for X.

假设我有一个名为FSM. 最终在我的代码中,FSM可以创建多个实例。其中一个FSM的属性是int X它不是一成不变的,每个实例FSM应该有其存在的价值X

Now, one of FSM's attributes is another structure submachinewhich needs to read the value of Xlike this:

现在, 的一个FSM属性是另一个结构submachine,它需要X像这样读取 的值:

struct FSM
{
  public:
    int x;

    int getX(){return x;}

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

This gives the following error:

这给出了以下错误:

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

错误:'FSM::getX':非静态成员函数的非法调用

My question is, submachineis a member of FSM, so shouldn't it have access to local instances of all the attributes of FSM? And if not, when we create an instance of FSM, wouldn't we be creating an instance of all its members i.e. submachine? And if so, then why do we need to create an object that onentry()needs?

我的问题是,它submachine是 的成员FSM,所以它不应该访问 的所有属性的本地实例FSM吗?如果没有,当我们创建 的实例时FSM,我们是否会创建其所有成员的实例,即submachine?如果是这样,那为什么我们需要创建一个需要的对象onentry()

I am assuming the compiler is correct, so I would also want to know if there's a way to make this work.

我假设编译器是正确的,所以我也想知道是否有办法让这个工作。

NOTE: Unfortunately, the instances of the inner structures (submachine) are instantiated when an event is called and thus I can only define the type, and not instantiate objects for them in FSM.

注意:不幸的是,内部结构 ( submachine) 的实例在调用事件时被实例化,因此我只能定义类型,而不能在FSM.

回答by Oliver Charlesworth

my question is, submachine is a member of FSM, so it should have access to local instances of all the attributes of FSM, no?

我的问题是,submachine 是 FSM 的成员,所以它应该可以访问 FSM 的所有属性的本地实例,不是吗?

No. Unlike in Java, inner class objects don't have an implicit reference to an outer object.

不。与Java 不同,内部类对象没有对外部对象的隐式引用。

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

我们不会创建其所有成员的实例,即 submachine?

submachineis a type, not a member variable. If you wanted a member variable, you'd have to do something like this:

submachine类型,而不是成员变量。如果你想要一个成员变量,你必须做这样的事情:

struct FSM {
    struct submachine {
        ...
    };

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

And if you want smto "see" its parent object, you'll need to pass it explicitly:

如果你想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
};

Note that the same principle applies for instances of submachinethat aren't member variables. If you want them to be able to access an FSMinstance, you'll need to pass a reference to one.

请注意,相同的原则适用于submachine非成员变量的实例。如果您希望它们能够访问FSM实例,则需要传递对实例的引用。

Note also that you could use a pointer rather than a reference. In fact, a pointer offers greater flexibility in many cases.

另请注意,您可以使用指针而不是引用。事实上,指针在许多情况下提供了更大的灵活性。

回答by Useless

consider that in your example, I can legally write a free function

考虑在你的例子中,我可以合法地编写一个免费的函数

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

where there is noFSM instance that subcould refer to.

其中没有sub可以引用的FSM 实例。

Either, as Oli says, have the submachineobject store a reference to its parent FSMobject, or perhaps just pass the value of xdirectly into onentry(it isn't clear how it gets invoked).

或者,正如 Oli 所说,让submachine对象存储对其父FSM对象的引用,或者可能只是将 的值x直接传递到onentry(尚不清楚它是如何被调用的)。



From a quick look at the Boost.MSM docsI found this note on non-default-constructed submachines.

通过快速浏览Boost.MSM 文档,我发现了关于non-default-constructed submachines 的注释。

It's pretty ugly, I don't understand the backend enough to paraphrase it here, and the literal code won't make enough sense in isolation to be worth pasting.

它非常丑陋,我对后端的理解不够充分,无法在此处对其进行解释,而且文字代码单独来看也没有足够的意义值得粘贴。

The example code linked from there also shows the submachine's entry method with the following signature:

从那里链接的示例代码还显示了具有以下签名的子机器的输入方法:

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

if that's accurate, you can either store a pointer to your outer state machine on_entry, or extract the value of x there and record it in the submachine.

如果这是准确的,您可以存储一个指向外部状态机的指针on_entry,或者在那里提取 x 的值并将其记录在子机中。

回答by Kevin Grant

Note that declaring struct submachineonly defines the type; it does not actually create a field in the class of that type.

请注意,声明struct submachine仅定义类型;它实际上并未在该类型的类中创建字段。

You would need one of the following:

您将需要以下其中一项:

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

or

或者

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

This makes mysubthe field, and you then access it in the same way that you'd access x.

这将创建mysub该字段,然后您可以像访问x.

The definition of submachineneeds to include a specific FSM(e.g. a pointer field FSM*, and probably a constructor like submachine(FSM* fsm): fsm_(fsm) {}to initialize it) so that you can say fsm_->getX()to access a certain Xvalue.

定义submachine需要包含一个特定的FSM(例如一个指针字段FSM*,可能还有一个构造函数submachine(FSM* fsm): fsm_(fsm) {}来初始化它),以便您可以fsm_->getX()访问某个X值。

回答by jxh

I am only making a guess at what you want to do, but if my guess is correct, you might be thinking of something like the below.

我只是猜测您想做什么,但如果我的猜测是正确的,您可能会想到以下内容。

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