www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - How to new a class object in a struct

reply zhang <bitworld qq.com> writes:
Here are some codes:

class AClass
{
    int a = 10;
}

struct AStruct
{
    AClass aclass;

//    this()  // can't do this in a struct
//    {
//        aclass = new AClass()
//    }

    this(AClass aclass_)
    {
        aclass = aclass_;
    }
}


int main(string[] args)
{
    AStruct astruct;
    int a = astruct.aclass.a;
    writefln("%d", a);
    return 0;
}


In D, this() is prohibited in a struct. So
   AStruct astruct
will leave the aclass object to be null. It's not like the way in C++, the
aclass object will be created automatically.

It always leads some problems when doing porting from C++ to D.

My solution is to use class instead of struct. Then I can create the aclass
object in this() when I new an AStruct.

Any suggestion? 
Thanks.

----------
Zhang <bitworld qq.com>
Sep 01 2011
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 09/01/2011 04:10 PM, zhang wrote:
 Here are some codes:

 class AClass
 {
      int a = 10;
 }

 struct AStruct
 {
      AClass aclass;

 //    this()  // can't do this in a struct
 //    {
 //        aclass = new AClass()
 //    }

      this(AClass aclass_)
      {
          aclass = aclass_;
      }
 }


 int main(string[] args)
 {
      AStruct astruct;
      int a = astruct.aclass.a;
      writefln("%d", a);
      return 0;
 }


 In D, this() is prohibited in a struct. So
     AStruct astruct
 will leave the aclass object to be null. It's not like the way in C++, the
aclass object will be created automatically.

 It always leads some problems when doing porting from C++ to D.

 My solution is to use class instead of struct. Then I can create the aclass
object in this() when I new an AStruct.

 Any suggestion?
 Thanks.

 ----------
 Zhang<bitworld qq.com>
This works: class AClass { int a = 10; } struct AStruct { AClass aclass; // this() disable; // will be in the next DMD release static AStruct opCall() { return AStruct(new AClass()); } static AStruct opCall(AClass aclass_) { AStruct result = void; result.aclass = aclass_; return result; } } int main(string[] args) { auto astruct = AStruct(); int a = astruct.aclass.a; writefln("%d", a); return 0; }
Sep 01 2011
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
You could do something like this:

class AClass
{
   int a = 10;
}

struct AStruct
{
   // Never use this directly, except inside the "aclass" property functions
   private AClass _aclass;

     property AClass aclass()
    {
        if(_aclass is null)
            _aclass = new AClass();
        return _aclass;
    }

     property void aclass(AClass c)
    {
        _aclass = c;
    }
}

-------------------------------
Not sent from an iPhone.
Sep 01 2011
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 01 Sep 2011 13:31:29 -0400, Nick Sabalausky <a a.a> wrote:

 You could do something like this:

 class AClass
 {
    int a = 10;
 }

 struct AStruct
 {
    // Never use this directly, except inside the "aclass" property  
 functions
    private AClass _aclass;

      property AClass aclass()
     {
         if(_aclass is null)
             _aclass = new AClass();
         return _aclass;
     }

      property void aclass(AClass c)
     {
         _aclass = c;
     }
 }

 -------------------------------
 Not sent from an iPhone.
This doesn't work. It has the same problem as AA's currently do: foo(AStruct str) { str.aclass.a = 5; } void main() { AStruct str; // assert(str.aclass.a == 10); foo(str); assert(str.aclass.a == 5); // fails unless you comment out the line above. } And to answer the OP's question, the easiest thing to do is create a constructor function (not a ctor, because you can't have default ctors). Yes, it's annoying, but it's about as close as you can get to C++. struct AStruct { static AStruct create() {return AStruct(new AClass());} } auto str = AStruct.create(); Until the next release, there is no way to force a user to always call such a function. The next relase allows disable this(), which should disable simply declaring a struct. This is an alternative to Timon's opCall solution. -Steve
Sep 01 2011
parent reply "Nick Sabalausky" <a a.a> writes:
"Steven Schveighoffer" <schveiguy yahoo.com> wrote in message 
news:op.v046zvlfeav7ka localhost.localdomain...
 On Thu, 01 Sep 2011 13:31:29 -0400, Nick Sabalausky <a a.a> wrote:

 You could do something like this:

 class AClass
 {
    int a = 10;
 }

 struct AStruct
 {
    // Never use this directly, except inside the "aclass" property 
 functions
    private AClass _aclass;

      property AClass aclass()
     {
         if(_aclass is null)
             _aclass = new AClass();
         return _aclass;
     }

      property void aclass(AClass c)
     {
         _aclass = c;
     }
 }

 -------------------------------
 Not sent from an iPhone.
This doesn't work. It has the same problem as AA's currently do: foo(AStruct str) { str.aclass.a = 5; } void main() { AStruct str; // assert(str.aclass.a == 10); foo(str); assert(str.aclass.a == 5); // fails unless you comment out the line above. }
Could using postblit solve that (or am I misunderstanding the issue)?
Sep 01 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 09/01/2011 10:35 PM, Nick Sabalausky wrote:
 "Steven Schveighoffer"<schveiguy yahoo.com>  wrote in message
 news:op.v046zvlfeav7ka localhost.localdomain...
 On Thu, 01 Sep 2011 13:31:29 -0400, Nick Sabalausky<a a.a>  wrote:

 You could do something like this:

 class AClass
 {
     int a = 10;
 }

 struct AStruct
 {
     // Never use this directly, except inside the "aclass" property
 functions
     private AClass _aclass;

       property AClass aclass()
      {
          if(_aclass is null)
              _aclass = new AClass();
          return _aclass;
      }

       property void aclass(AClass c)
      {
          _aclass = c;
      }
 }

 -------------------------------
 Not sent from an iPhone.
This doesn't work. It has the same problem as AA's currently do: foo(AStruct str) { str.aclass.a = 5; } void main() { AStruct str; // assert(str.aclass.a == 10); foo(str); assert(str.aclass.a == 5); // fails unless you comment out the line above. }
Could using postblit solve that (or am I misunderstanding the issue)?
Postblit has no access to the original struct, so how would you solve the issue using postblit?
Sep 01 2011
prev sibling next sibling parent reply "Marco Leise" <Marco.Leise gmx.de> writes:
Am 01.09.2011, 16:10 Uhr, schrieb zhang <bitworld qq.com>:

 Here are some codes:

 class AClass
 {
     int a = 10;
 }

 struct AStruct
 {
     AClass aclass;

 //    this()  // can't do this in a struct
 //    {
 //        aclass = new AClass()
 //    }

     this(AClass aclass_)
     {
         aclass = aclass_;
     }
 }


 int main(string[] args)
 {
     AStruct astruct;
     int a = astruct.aclass.a;
     writefln("%d", a);
     return 0;
 }


 In D, this() is prohibited in a struct. So
    AStruct astruct
 will leave the aclass object to be null. It's not like the way in C++,  
 the aclass object will be created automatically.

 It always leads some problems when doing porting from C++ to D.

 My solution is to use class instead of struct. Then I can create the  
 aclass object in this() when I new an AStruct.

 Any suggestion?
 Thanks.

 ----------
 Zhang <bitworld qq.com>
C++ has an easy position because it handles structs almost like classes. The only difference I notice is that everything is public by default in a struct. So technically your structs would probably better be matched by D classes. But that's of course not what you intended in the C++ code in the first place. :)
Sep 01 2011
parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, September 01, 2011 16:26 Marco Leise wrote:
 C++ has an easy position because it handles structs almost like classes.
 The only difference I notice is that everything is public by default in a
 struct.
That _is_ the only difference between structs and classes in C++. - Jonathan M Davis
Sep 01 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 09/01/2011 06:45 PM, Jonathan M Davis wrote:
 On Thursday, September 01, 2011 16:26 Marco Leise wrote:
 C++ has an easy position because it handles structs almost like classes.
 The only difference I notice is that everything is public by default in a
 struct.
That _is_ the only difference between structs and classes in C++. - Jonathan M Davis
Default inheritance protection is different, too. Andrei
Sep 01 2011
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Thursday, September 01, 2011 20:33:05 Andrei Alexandrescu wrote:
 On 09/01/2011 06:45 PM, Jonathan M Davis wrote:
 On Thursday, September 01, 2011 16:26 Marco Leise wrote:
 C++ has an easy position because it handles structs almost like
 classes.
 The only difference I notice is that everything is public by default
 in a struct.
That _is_ the only difference between structs and classes in C++. - Jonathan M Davis
Default inheritance protection is different, too.
Well, that would arguably be part of "everything is public by default," but it's a good point. - Jonathan M Davis
Sep 01 2011
prev sibling parent Mehrdad <wfunction hotmail.com> writes:
On 9/1/2011 7:10 AM, zhang wrote:
 It's not like the way in C++, the aclass object will be created automatically.
Yes, because D classes are NOT equal to C++ classes. D classes are reference types, and C++ "classes" are structs. So D classes *pointers* to C++ classes, which are obviously NULL by default.
Sep 01 2011