www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Best way to reference an array in a child class...

reply "captain_fid" <bell.hue gmail.com> writes:
Sorry for the very basic question. Much still alludes me with 
this language. I appreciate the forum.

struct S
{
Mar 06 2014
parent reply "captain_fid" <bell.hue gmail.com> writes:
On Thursday, 6 March 2014 at 19:19:29 UTC, captain_fid wrote:
 Sorry for the very basic question. Much still alludes me with 
 this language. I appreciate the forum.

 struct S
 {
Wow sorry for that. I'm a moron... don't press <tab> <enter>... struct S { int a; string b; } class A { S[]* pointer_to_list; abstract... } class B: A { S[] items = [ {10, "first"}, {20, "second"}]; this() { pointer_to_list = &items; } } My problem is in de-referencing later (seg fault). Is this even the best way? I Really need to access the array in a derived class. 'S' (I believe) really is best as a Structure. Any suggestions. Thanks in advance (and sorry for the rough start).
Mar 06 2014
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 06 Mar 2014 14:31:52 -0500, captain_fid <bell.hue gmail.com> wrote:

 On Thursday, 6 March 2014 at 19:19:29 UTC, captain_fid wrote:
 Sorry for the very basic question. Much still alludes me with this  
 language. I appreciate the forum.

 struct S
 {
Wow sorry for that. I'm a moron... don't press <tab> <enter>... struct S { int a; string b; } class A { S[]* pointer_to_list; abstract... } class B: A { S[] items = [ {10, "first"}, {20, "second"}]; this() { pointer_to_list = &items; } } My problem is in de-referencing later (seg fault). Is this even the best way? I Really need to access the array in a derived class. 'S' (I believe) really is best as a Structure. Any suggestions. Thanks in advance (and sorry for the rough start).
I would highly suggest to just use S[] and not S[]*. A slice is already a reference (coupled with a length). You can read more about D arrays and slices here: http://dlang.org/d-array-article.html -Steve
Mar 06 2014
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/06/2014 11:40 AM, Steven Schveighoffer wrote:

 class A
 {
    S[]* pointer_to_list;
    abstract...
 }
 I would highly suggest to just use S[] and not S[]*. A slice is already
 a reference (coupled with a length).
But what if there are elements added to B.items later on? I assumed the OP wanted a true reference.
 You can read more about D arrays and slices here:

 http://dlang.org/d-array-article.html
My I suggest you do the same. :o)
 -Steve
Ali
Mar 06 2014
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 06 Mar 2014 14:47:49 -0500, Ali =C3=87ehreli <acehreli yahoo.com=
 wrote:
 On 03/06/2014 11:40 AM, Steven Schveighoffer wrote:

  >> class A
  >> {
  >>    S[]* pointer_to_list;
  >>    abstract...
  >> }

  > I would highly suggest to just use S[] and not S[]*. A slice is  =
 already
  > a reference (coupled with a length).

 But what if there are elements added to B.items later on? I assumed th=
e =
 OP wanted a true reference.
First, it's very cumbersome to work with a pointer to an array. All arra= y = syntax sugar does not peek through the reference, you have to * everythi= ng. Second, it's very difficult to get an array, just by itself, in the heap= . = And you don't want to store a reference to a stack-frame slice. I think there is a good reason you seldom see code that has pointers to = = array in D, the above code snippet seems to me like a programmer who = doesn't understand what a D slice is. Actually, given the subject of this post, I take it back. The best way t= o = reference an array in a child class, especially one of a static type, is= = to not have another copy in the child class :)
  > You can read more about D arrays and slices here:
  >
  > http://dlang.org/d-array-article.html

 My I suggest you do the same. :o)
TL;DR ;) -Steve
Mar 06 2014
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 06 Mar 2014 15:02:14 -0500, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 Second, it's very difficult to get an array, just by itself, in the  
 heap. And you don't want to store a reference to a stack-frame slice.
Sorry, I meant an array *reference*, not an array. Clearly allocating an array in the heap is easy, but allocating a pointer to an array is not :) -Steve
Mar 06 2014
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/06/2014 12:02 PM, Steven Schveighoffer wrote:

 The best way
 to reference an array in a child class, especially one of a static type,
 is to not have another copy in the child class :)
Agreed. Alternatively, a member function in the child class could return a slice. Ali
Mar 06 2014
parent reply "captain_fid" <bell.hue gmail.com> writes:
On Thursday, 6 March 2014 at 21:26:11 UTC, Ali Çehreli wrote:
 On 03/06/2014 12:02 PM, Steven Schveighoffer wrote:

 The best way
 to reference an array in a child class, especially one of a
static type,
 is to not have another copy in the child class :)
Agreed. Alternatively, a member function in the child class could return a slice. Ali
Steve, thanks for the link and the nicely written article. Also for the assessment on pointer syntax, I'd love to avoid if possible (especially w/ limitations you noted). I had been spending time over at http://dlang.org/arrays.html and had forgotten (or never understood) dynamic arrays were passed by slices. That link only talks about passing static arrays (IIRC). Keeping track of 'what being passed how' is tough for this programmer. Your suggestion Ali (of not accessing the base member in the child was great) and it works properly. Believe if I understand what you are suggesting above is never to have the array in base? simply retrieve slice through the child member function?
Mar 06 2014
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 06 Mar 2014 17:05:12 -0500, captain_fid <bell.hue gmail.com> wro=
te:

 On Thursday, 6 March 2014 at 21:26:11 UTC, Ali =C3=87ehreli wrote:
 On 03/06/2014 12:02 PM, Steven Schveighoffer wrote:

 The best way
 to reference an array in a child class, especially one of a
static type,
 is to not have another copy in the child class :)
Agreed. Alternatively, a member function in the child class could =
 return a slice.

 Ali
Steve, thanks for the link and the nicely written article. Also for th=
e =
 assessment on pointer syntax, I'd love to avoid if possible (especiall=
y =
 w/ limitations you noted).

 I had been spending time over at http://dlang.org/arrays.html and had =
=
 forgotten (or never understood) dynamic arrays were passed by slices. =
=
 That link only talks about passing static arrays (IIRC). Keeping track=
=
 of 'what being passed how' is tough for this programmer.

 Your suggestion Ali (of not accessing the base member in the child was=
=
 great) and it works properly.

 Believe if I understand what you are suggesting above is never to have=
=
 the array in base? simply retrieve slice through the child member  =
 function?
I think what Ali means is: class A { abstract S[] items(); } class B : A { S[] _items =3D [ {10, "first"}, {20, "second"}]; override S[] items() { return _items;} } What I was saying is, if you know the items are going to be stored in th= e = object, just store them in the base: class A { S[] items; } class B : A { this() {items =3D [ {10, "first"}, {20, "second"}];} } This way, both the derived and the base will always see the same items, = = and you only store it in the object once. Obviously if you store the ite= ms = elsewhere in some derivatives, Ali's idea is preferable. -Steve
Mar 06 2014
parent reply "captain_fid" <bell.hue gmail.com> writes:
On Thursday, 6 March 2014 at 22:16:50 UTC, Steven Schveighoffer 
wrote:
 On Thu, 06 Mar 2014 17:05:12 -0500, captain_fid 
 <bell.hue gmail.com> wrote:

 On Thursday, 6 March 2014 at 21:26:11 UTC, Ali Çehreli wrote:
 On 03/06/2014 12:02 PM, Steven Schveighoffer wrote:

 The best way
 to reference an array in a child class, especially one of a
static type,
 is to not have another copy in the child class :)
Agreed. Alternatively, a member function in the child class could return a slice. Ali
Steve, thanks for the link and the nicely written article. Also for the assessment on pointer syntax, I'd love to avoid if possible (especially w/ limitations you noted). I had been spending time over at http://dlang.org/arrays.html and had forgotten (or never understood) dynamic arrays were passed by slices. That link only talks about passing static arrays (IIRC). Keeping track of 'what being passed how' is tough for this programmer. Your suggestion Ali (of not accessing the base member in the child was great) and it works properly. Believe if I understand what you are suggesting above is never to have the array in base? simply retrieve slice through the child member function?
I think what Ali means is: class A { abstract S[] items(); } class B : A { S[] _items = [ {10, "first"}, {20, "second"}]; override S[] items() { return _items;} } What I was saying is, if you know the items are going to be stored in the object, just store them in the base: class A { S[] items; } class B : A { this() {items = [ {10, "first"}, {20, "second"}];} } This way, both the derived and the base will always see the same items, and you only store it in the object once. Obviously if you store the items elsewhere in some derivatives, Ali's idea is preferable. -Steve
Yes Steve! Even if the title of the thread is off, the original intent was what you've shown. For a reason (probably duplicate definitions in base and child) I would end up with items in B and not visible in A. I didn't understand the syntax for performing the above. I owe you guys a beer (or something). Definitely a learning lesson.
Mar 06 2014
parent reply "captain_fid" <bell.hue gmail.com> writes:
    this() {items = [ {10, "first"}, {20, "second"}];}
strangely enough, when modeling this the first time (using items as a class) and 'new item() syntax) there was no real issue. I thought using a static array of structs in the children would be more efficient when instantiating the objects. Never mind whether its true or not - Speed isn't a really a concern, learning is.
Mar 06 2014
next sibling parent reply "captain_fid" <bell.hue gmail.com> writes:
Well, actually... take it back.

When I did try this syntax, I receive(d) the following error. I 
then went and created this test which I thought couldn't go wrong.

with both dmd and gdc ...



struct S
{
   int a;
   string b;
}

class A
{
    S[] items;
    abstract void doit();
}

class B: A
{
    this() {items = [ {10, "first"}, {20, "second"}];}    // line 
21
    override void doit() { }
}

(21): Error: found '}' when expecting ';' following statement
(21): Error: found ',' instead of statement
Mar 06 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
captain_fid:

 struct S
 {
   int a;
   string b;
 }

 class A
 {
    S[] items;
    abstract void doit();
 }

 class B: A
 {
    this() {items = [ {10, "first"}, {20, "second"}];}    // 
 line 21
    override void doit() { }
 }

 (21): Error: found '}' when expecting ';' following statement
 (21): Error: found ',' instead of statement
For reasons I don't know that {} syntax doesn't always work in D. So try: this() { this.items = [S(10, "first"), S(20, "second")]; } Bye, bearophile
Mar 06 2014
parent "captain_fid" <bell.hue gmail.com> writes:
On Friday, 7 March 2014 at 00:10:20 UTC, bearophile wrote:
 captain_fid:

 struct S
 {
  int a;
  string b;
 }

 class A
 {
   S[] items;
   abstract void doit();
 }

 class B: A
 {
   this() {items = [ {10, "first"}, {20, "second"}];}    // 
 line 21
   override void doit() { }
 }

 (21): Error: found '}' when expecting ';' following statement
 (21): Error: found ',' instead of statement
For reasons I don't know that {} syntax doesn't always work in D. So try: this() { this.items = [S(10, "first"), S(20, "second")]; } Bye, bearophile
Going to have to buy the whole bar a round. Thanks bearophile for the quick fix!
Mar 06 2014
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 06 Mar 2014 17:44:09 -0500, captain_fid <bell.hue gmail.com> wrote:

    this() {items = [ {10, "first"}, {20, "second"}];}
strangely enough, when modeling this the first time (using items as a class) and 'new item() syntax) there was no real issue. I thought using a static array of structs in the children would be more efficient when instantiating the objects. Never mind whether its true or not - Speed isn't a really a concern, learning is.
I missed this the first time. That is a difference between my code and your code. Mine creates a new instance of an array on *object* initialization, yours creates ONE instance of an array, that all objects share. This is not necessarily a good thing. Because you've created a mutable version of the array. I believe it is initialized on startup from the heap. One really bad thing is, the same array is used if you initialize from multiple threads. And it's mutable, making it implicitly shared even though it shouldn't be. You should make the array immutable and static, or else initialize it in the constructor. I don't know your use case, so it's hard to say what you should do. -Steve
Mar 07 2014
parent "captain_fid" <bell.hue gmail.com> writes:
On Friday, 7 March 2014 at 13:57:31 UTC, Steven Schveighoffer 
wrote:
 On Thu, 06 Mar 2014 17:44:09 -0500, captain_fid 
 <bell.hue gmail.com> wrote:

   this() {items = [ {10, "first"}, {20, "second"}];}
strangely enough, when modeling this the first time (using items as a class) and 'new item() syntax) there was no real issue. I thought using a static array of structs in the children would be more efficient when instantiating the objects. Never mind whether its true or not - Speed isn't a really a concern, learning is.
I missed this the first time. That is a difference between my code and your code. Mine creates a new instance of an array on *object* initialization, yours creates ONE instance of an array, that all objects share. This is not necessarily a good thing. Because you've created a mutable version of the array. I believe it is initialized on startup from the heap. One really bad thing is, the same array is used if you initialize from multiple threads. And it's mutable, making it implicitly shared even though it shouldn't be. You should make the array immutable and static, or else initialize it in the constructor. I don't know your use case, so it's hard to say what you should do. -Steve
 I don't know your use case, so it's hard to say what you 
 should do.
Steve, I don't think I know my use case -- So it's not you. I'm attempting to model hardware, where 'items' in this case are an static array of registers. Single threaded (for now). Mainly, this a learning opportunity to get a better understanding of D for future comparison (vs. C++).
 This is not necessarily a good thing. Because you've created a 
 mutable version of the array. I believe it is initialized on 
 startup from the heap.
Lot to learn. I understand initialized from the heap, but do you mean at program startup, or object instantiation? If program, I would have expected that with __gshared (globals) only, not with this.
 One really bad thing is, the same array is used if you 
 initialize from multiple threads. And it's mutable, making it 
 implicitly shared even though it shouldn't be. You should make 
 the array immutable and static, or else initialize it in the 
 constructor.
I appreciate your suggestions and the patience.
Mar 07 2014
prev sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/06/2014 02:05 PM, captain_fid wrote:

 Your suggestion Ali (of not accessing the base member in the child was
 great) and it works properly.

 Believe if I understand what you are suggesting above is never to have
 the array in base? simply retrieve slice through the child member 
function? Yes, but it also depends on the need. I assumed that the base class needed a slice of elements from the base class. Will the slice of elements ever change? If no, then the base could take them at construction time and use them in the future: import std.stdio; class B { const(int[]) items; this(const(int[]) items) // <-- Requires elements // during construction { this.items = items; } final void do_work() { writeln(items); } } class D : B { this() { super([ 1, 2, 3]); // Items are determined here } } void main() { auto d = new D(); d.do_work(); } Alternatively, and especially if the elements will change at run time, the derived class can hold on to the elements and can provide them as the base class needs: import std.stdio; class B { abstract const(int)[] items(); final void do_work() { writeln(items()); } } class D : B { int[] myItems; this() { myItems = [ 1, 2, 3]; } void add(int[] items) { myItems ~= items; } override const(int)[] items() { return myItems; } } void main() { auto d = new D(); d.do_work(); // 1, 2, 3 // Add more later on d.add([ 4, 5, 6 ]); d.do_work(); // 1, 2, 3, 4, 5, 6 } Ali
Mar 06 2014
prev sibling parent "captain_fid" <bell.hue gmail.com> writes:
Steve and Ali, Thanks for the quick helpful suggestions. In this 
case I probably don't need the expansion (but certainly look 
forward to understanding either way).

I'll certainly hit that reference (Special thanks Ali for your 
book. I've enjoyed it over the past few months)
Mar 06 2014
prev sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/06/2014 11:31 AM, captain_fid wrote:
 On Thursday, 6 March 2014 at 19:19:29 UTC, captain_fid wrote:
 Sorry for the very basic question. Much still alludes me with this
 language. I appreciate the forum.

 struct S
 {
Wow sorry for that. I'm a moron... don't press <tab> <enter>... struct S { int a; string b; } class A { S[]* pointer_to_list; abstract... } class B: A { S[] items = [ {10, "first"}, {20, "second"}]; this() { pointer_to_list = &items; } } My problem is in de-referencing later (seg fault). Is this even the best way? I Really need to access the array in a derived class. 'S' (I believe) really is best as a Structure. Any suggestions. Thanks in advance (and sorry for the rough start).
You need to dereference the pointer by * and you would be using a slice: import std.stdio; import std.conv; struct S { int a; string b; } class A { S[]* pointer_to_list; void access() { foreach (e; *pointer_to_list) { // <-- NOTE * writeln(e); } } } class B: A { S[] items = [ {10, "first"}, {20, "second"}]; this() { pointer_to_list = &items; } } void main() { auto b = new B(); foreach (i; 30 .. 40) { b.items ~= S(i, i.to!string); } b.access(); } As a side note, I would make A take the slice as a reference parameter, rather that B accessing A's member directly. It is better for maintainability: class A { S[]* pointer_to_list; this(ref S[] list) // <-- BETTER { this.pointer_to_list = &list; } // ... } class B: A { // ... this() { super(items); // <-- BETTER } } Ali
Mar 06 2014