开发者

How to refer to enclosing instance from C++ inner class?

开发者 https://www.devze.com 2023-03-09 13:04 出处:网络
In C++, an object refers to itself via this. But how does an instance of an inner class refer to the instance of its enclosing class?

In C++, an object refers to itself via this.

But how does an instance of an inner class refer to the instance of its enclosing class?

class Zoo
{
    class Bear 
    {
        void runAway()
        {
            EscapeService::helpEscapeFrom (
                this, /* the Bear */ 
                ??? /* I need a pointer to the Bear's Zoo here */);
        }
    };
};

EDIT

My understanding of how non-static inner classes work is that Bear can access the members of its Zoo, therefore it has an implicit pointer to Zoo. I don't want to access the members in this case; I'm trying to g开发者_StackOverflow社区et that implicit pointer.


Unlike Java, inner classes in C++ do not have an implicit reference to an instance of their enclosing class.

You can simulate this by passing an instance, there are two ways :

pass to the method :

class Zoo
{
    class Bear 
    {
        void runAway( Zoo & zoo)
        {
            EscapeService::helpEscapeFrom (
                this, /* the Bear */ 
                zoo );
        }
    };
}; 

pass to the constructor :

class Zoo
{
    class Bear
    {
        Bear( Zoo & zoo_ ) : zoo( zoo_ ) {}
        void runAway()
        {
            EscapeService::helpEscapeFrom (
                this, /* the Bear */ 
                zoo );
        }

        Zoo & zoo;
    };
}; 


Inner classes are not special, and don't have any link to their outer class built-in. If you want to access the outer class, then pass a pointer or reference, just as you would with any other class.


You can access the outer class instance from an inner class instance by using offsetof.
This has zero overhead compared to the pointer/reference solution.
It's a bit dirty but it gets the job done.
For example:

#include <cstddef>
struct enclosing {
    struct inner {
        enclosing& get_enclosing() {
            return *(enclosing*)((char*)this - offsetof(enclosing, i));
        }
        void printX() {
            std::cout << get_enclosing().x << '\n';
        }
    } i;
    int x;
};
int main() {
    enclosing e;
    e.x = 5;
    e.i.printX();
}

P.S.
offsetof makes some assumptions about the type. In C++98 the type has to be a POD and in C++11 the type has to be "standard layout".
Here's a reference: http://www.cplusplus.com/reference/cstddef/offsetof/


An inner class has access to all members of the outer class, but it does not have an implicit reference to a parent class instance.

To answer your modifed Q:
No you cannot access that implicit pointer. I believe one can do so in Java but not in C++.

You will have to pass the outer class object explicitly through constructor or some other function to acheive this.

Technically as per C++03 standard(sec 11.8.1), a nested class does NOT have special access to its enclosing class.

But there is also this standard defect: openstd.org/jtc1/sc22/wg21/docs/cwg_defects.html#45 Not sure if this is closed.


There is no built-in mechanism to achieve this. You need to provide the pointer yourself, via constructor or some kind of SetParent function.


The C++ Standard says (section 11.8.1 [class.access.nest]):

The members of a nested class have no special access to members of an enclosing class, nor to classes or functions that have granted friendship to an enclosing class; the usual access rules (clause 11) shall be obeyed. The members of an enclosing class have no special access to members of a nested class; the usual access rules (clause 11) shall be obeyed.

(emphasis by me).

This means that there is no special relationship between the nested and enclosing class.


There is no implicitly created instance of the enclosing class when creating an instance of the nested class. It has to be done manually.

0

精彩评论

暂无评论...
验证码 换一张
取 消