Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't inner class *definitions* use their parent?

Tags:

c++

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?

like image 539
imallett Avatar asked Dec 17 '16 11:12

imallett


People also ask

Can inner classes access private members?

Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private.

Does inner class have access private variables?

So, yes; an object of type Outer::Inner can access the member variable var of an object of type Outer .

What is the difference between an inner class and a sub class?

An inner class is a class that is created inside of another class. A subclass is a class that extends another class.

Why do we need inner classes in Java?

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.


2 Answers

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.

like image 161
Sergey Kalinichenko Avatar answered Oct 30 '22 18:10

Sergey Kalinichenko


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;
};
like image 43
Owen Delahoy Avatar answered Oct 30 '22 18:10

Owen Delahoy