www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Nested sibling classes

reply seany <seany uni-bonn.de> writes:
Please Consider the code:

         import std.stdio;

         class a {

         public:
              this(){}
             ~this(){}

             class b {

             public:
                     this.outer.c C = new this.outer.c();
                      this() {
                             writeln(this.C.i);
                     }
                     ~this() {}

             }

             class c {
             public:
                      this() {}
                     ~this() {}
                     int i = 10;
             }

         }


         int main () {

             int [int][int] test;

             test[0][20] = 19;
             writeln(Test[0][20]);


             a A = new A();
             a.b B = a.new a.b();
             return 0;
         }


Compiling with dmd tells me:
`test.d(12): Error: undefined identifier `` this.outer.c `` ` (i 
used two backticks, but i can't seem tobe escaping the backtick 
character correctly in this forum)

On fish shell we have:
❯ dmd --version
DMD64 D Compiler v2.101.2

Copyright (C) 1999-2022 by The D Language Foundation, All Rights 
Reserved written by Walter Bright


If i remove the "this.outer" and just write, c C = new c(); then 
i have:

`test.d(12): Error: cannot construct nested class ` c ` because 
no implicit ` this ` reference to outer class ` a ` is available`


How can I make it, that classes b and c can access each other, 
and create instances of each other freely? Thank you.
Jan 12 2023
next sibling parent reply Salih Dincer <salihdb hotmail.com> writes:
On Thursday, 12 January 2023 at 17:05:04 UTC, seany wrote:

 How can I make it, that classes b and c can access each other, 
 and create instances of each other freely? Thank you.
Ignoring the typos you could try auto and static: ```d class a { //outer static class b { // inner 1 c C; this() { this.C = new c; //writeln(this.C.i); } } static class c { // inner 2 int i = 10; } } int main () { int[21][1] test; test[0][20] = 19; assert(test[0][20] == 19); auto B = new a.b; auto C = new a.c; assert(B.C.i == 10); assert(C.i == 10); return 0; } ``` SDB 79
Jan 12 2023
parent reply seany <seany uni-bonn.de> writes:
On Thursday, 12 January 2023 at 17:41:39 UTC, Salih Dincer wrote:
 On Thursday, 12 January 2023 at 17:05:04 UTC, seany wrote:

 How can I make it, that classes b and c can access each other, 
 and create instances of each other freely? Thank you.
Ignoring the typos you could try auto and static: ```d class a { //outer static class b { // inner 1 c C; this() { this.C = new c; //writeln(this.C.i); } } static class c { // inner 2 int i = 10; } } int main () { int[21][1] test; test[0][20] = 19; assert(test[0][20] == 19); auto B = new a.b; auto C = new a.c; assert(B.C.i == 10); assert(C.i == 10); return 0; } ``` SDB 79
Hi Moving the "new c" within the this() function indeed solved it. Thank you for pointing out the typos. Please, can you explain what role "static" plays here? Thank you again
Jan 12 2023
parent Salih Dincer <salihdb hotmail.com> writes:
On Thursday, 12 January 2023 at 17:46:45 UTC, seany wrote:
 
 Please, can you explain what role "static" plays here? Thank 
 you again
Of course, there are actually 2 paragraphs of information and examples [here]( https://dlang.org/spec/class.html#nested-context):
 Non-static nested classes work by containing an extra hidden 
 member (called the context pointer) that is the frame pointer 
 of the enclosing function if it is nested inside a function, or 
 the this reference of the enclosing class's instance if it is 
 nested inside a class.
 
 When a non-static nested class is instantiated, the context 
 pointer is assigned before the class's constructor is called, 
 therefore the constructor has full access to the enclosing 
 variables. A non-static nested class can only be instantiated 
 when the necessary context pointer information is available.
SDB 79
Jan 12 2023
prev sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 1/12/23 12:05 PM, seany wrote:

 How can I make it, that classes b and c can access each other, and 
 create instances of each other freely? Thank you.
 
So to just point out something that wasn't discussed by Salih: When you declare a field of a class with an initializer, *that initializer is run at compile-time*. Which means, that even if it did work, every instance of every b would start out with the same exact `C` object (not a copy, the same one). This is different than many other languages which treat initializers as part of the constructor (and run when you initialize a class). In D, the bits are simply copied into the new memory as the default state. For this reason you should almost *never* initialize a class reference in a non-static field. Consider that if you ever modified that instance named `C`, all new instances of `b` would have a reference to that modified instance! The reason the compiler doesn't like it is because it doesn't know how to initialize a `c` at compile time, since it needs the context pointer to the outer class. Just moving initialization into the constructor should fix the problem, you don't need to make them static. Now, maybe you didn't intend to have a nested class with a reference to the outer class, and in that case, you should make it static. -Steve
Jan 12 2023