On 01/17/2012 06:58 PM, Matej Nanut wrote:
On 17 January 2012 18:29, Timon Gehr<timon.g...@gmx.ch>  wrote:
I'm quite sure that the error in your code occurs for the same reason as in
the following code snippet:

class C{
    class D{}
    static make(){return new D();} // error
}

You can fix it by making D static:

class C{
    static class D{}
    static make(){return new D();} // ok
}

The reason is that non-static inner classes have an implicit 'outer'
property that links to the class it was created with. Therefore, to
construct them inside a member function, the implicit 'this' pointer is
needed. If the 'outer' property is actually unwanted, it is best to declare
inner classes as static.

Yes! If I move the class and its subclasses out of its outer class, and declare
them all static, it works!

Note that your `make' function is being called within class `D' in my example,
if I replace the names. However, the same thing applies.

Your explanation was nice, but now I'd like to know what the difference of a
non-static vs. a static class is, if they're defined top-level? Or are they then
the same?

Indeed they are the same. Anything top-level is implicitly static in D.

I don't expect anyone to thoroughly explain things to me, but
pointing out a good source, like a link or a book, would be really helpful.


I don't know if there is any, but I can explain to you the difference between static and non-static nested classes in detail:

class A{
    int x;
    static class B{void echo(){writeln(x);}} // n.g.
}

class A{
    int x;
    class B{void echo(){writeln(x);}} // ok
}

In other words, non-static nested classes can reference non-static fields of the enclosing class. In order to provide that functionality, non-static nested classes need the implicit 'outer' field. The first snippet is effectively rewritten to something like the following:

class A{
    int x;
    class B{A __outer; void echo(){writeln(__outer.x);}
}

Therefore, for constructing a class instance of type A.B, an instance of A must be provided as an initializer for the 'outer' field. If an instance of B is created in a member of A, the 'this' pointer gets used (and hence is required to be present), but you can also do:

void main() {
    auto a = new A;
auto b = a.new B; // construct an 'A.B' with 'a' in implicit 'outer' field
    a.x = 100;
    b.echo(); // writes '100'
}

This is probably one of the more obscure features of D. =)

I lack general knowledge in the OOP area and must really learn more about
it, as I've always been programming in C and could easily get away with it
as we were doing small-ish programs at university.

Reply via email to