It is well-known that one cannot have a member of the type you're defining:
class Foo {
Foo member;
};
The reason is that this is an infinitely recursive, infinitely large object. However, we can have static members:
class Foo {
static Foo member;
};
We can do this because Foo
is acting like a namespace; instances of Foo
do not contain .member
, so there's no infinite reference. Put another way, .member
belongs to the class, not to the instance. What I would like to do is very similar:
class Foo {
class Bar {
Foo member;
};
};
Once again, Foo
is acting like a namespace. Instances of Foo
are actually empty. I would have to make a non-static field Bar Foo::bar;
to start getting layout issues. Unfortunately, my compilers disagree (e.g. GCC):
<source>:3:14: error: field 'member' has incomplete type 'Foo'
Foo member;
^~~~~~
For what technical reason is this not allowed?
Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private.
So, yes; an object of type Outer::Inner can access the member variable var of an object of type Outer .
An inner class is a class that is created inside of another class. A subclass is a class that extends another class.
Inner classes are a security mechanism in Java. We know a class cannot be associated with the access modifier private, but if we have the class as a member of other class, then the inner class can be made private. And this is also used to access the private members of a class.
Long story short, it was easier to disallow this than to allow.
Here is an example that shows what could be difficult about it: C++ lets you combine nested class definition with a member declaration, like this:
class Foo {
class Bar {
Foo member;
} bar; // <<== Here
};
It is clear why this definition must be disallowed: unlike a class definition which could have been OK, member definition makes size computation impossible.
Of course the writers of the standard could have allowed class definitions to pass, at the expense of giving compiler writers additional work. However, it looks like they decided that allowing this feature is not worth the trouble, so they didn't make it an exception from the requirement of the class to be complete at the point of declaring an instance.
There is nothing wrong with what you what to do, and you can do so with different syntax.
Since the compiler wants to determine the size of class Bar, it needs to know the size of class Foo, But Foo's definition is not yet complete (The source code has not been entirely parsed by the compiler). The definition of Foo must be completed before using it in Bar.
Instead try forward declaring Bar inside Foo, then completing the definition of Bar after Foo, This way the size of Foo can be determined for use in Bar.
class Foo {
class Bar;
};
class Foo::Bar {
Foo member;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With