Error: 'this' is only defined in non-static member functions, not parse

Timon Gehr timon.gehr at gmx.ch
Tue Jan 17 11:25:28 PST 2012


On 01/17/2012 06:58 PM, Matej Nanut wrote:
> On 17 January 2012 18:29, Timon Gehr<timon.gehr at 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.



More information about the Digitalmars-d-learn mailing list