digitalmars.D - struct vs. class
- Martin (5/5) May 28 2007 Inspired by the recent discussion about iterator structs/classes I wante...
- Gregor Richards (25/31) May 28 2007 Firstly, your assertion about C++ is incorrect. C++ doesn't have both,
- Martin (11/36) May 28 2007 Yes, I know that - still, formally they are two different things (albeit...
- Derek Parnell (21/28) May 28 2007 They cannot and should not be 'unified' because their purpose is differe...
- Martin (2/35) May 29 2007 I know, but the differences between structs and classes go far beyond th...
- Hasan Aljudy (6/10) May 29 2007 That is why C++ sucks.
- Mike Parker (5/16) May 28 2007 When you want POD (plain old data) objects, with or without methods to
- janderson (5/29) May 28 2007 In c++ if you define a class without any virtual it effectively becomes
- Bill Baxter (19/33) May 29 2007 And you can tell they're considered different things by the annoying
- James Dennett (11/56) May 29 2007 I know of only one compiler which fails to compile that, and
- Bill Baxter (6/65) May 29 2007 Hey, you're right! I just tried it out in gcc. Works fine. And works
- James Dennett (5/73) May 29 2007 This corner's taken, I banished myself here after posting
- David B. Held (6/9) May 28 2007 The most important difference is that structs have value semantics and
- Martin (2/11) May 29 2007 I totally agree that both are needed, but is it necessary to tie the dif...
- David B. Held (13/28) May 29 2007 Unfortunately, you can't decide "on the spot" whether to use
- Martin (4/34) May 29 2007 But if I understand it correctly the only points where problems can occu...
- David B. Held (6/12) May 29 2007 I guess my problem is lack of motivation. I'm just not seeing the use
Inspired by the recent discussion about iterator structs/classes I wanted to ask - what's the design rationale behind having both structs and classes? In C++ the necessity was given by backwards compatibility but that doesn't apply to D of course. The only principal differences I can see (I'm not a D programmer (yet), so please correct me if I'm wrong) are a) that structs don't contain run-time meta information (a pointer to a vtable or however that works) and b) that struct variables are statically allocated as opposed to class variables which always seem to be pointers into dynamic memory. Somehow this looks really unorthogonal to me. Especially b) I find strange, can somebody explain the reason for this? cheers Martin
May 28 2007
Martin wrote:Inspired by the recent discussion about iterator structs/classes I wanted to ask - what's the design rationale behind having both structs and classes? In C++ the necessity was given by backwards compatibility but that doesn't apply to D of course. The only principal differences I can see (I'm not a D programmer (yet), so please correct me if I'm wrong) are a) that structs don't contain run-time meta information (a pointer to a vtable or however that works) and b) that struct variables are statically allocated as opposed to class variables which always seem to be pointers into dynamic memory. Somehow this looks really unorthogonal to me. Especially b) I find strange, can somebody explain the reason for this? cheers MartinFirstly, your assertion about C++ is incorrect. C++ doesn't have both, classes are just structs that are private by default, structs are just classes that are public by default. A C struct like this: struct Foo { int a, b; } is 100% equivalent (and passable as) a C++ class like this: class Bar { public: int a, b; } Structs in D are very light-weight. A struct is just a conglomeration of data. Passing a struct which contains two ints is exactly like passing the two ints, but syntactically less gross. Functions defined within a struct are basically syntactic sugar around functions that are defined taking the struct as the first argument. Classes are properly object oriented: They have hierarchies, methods are virtual, etc. As such, they're (comparably to structs) heavyweight: They have classinfo, are allocated on the heap, method calls require looking in a vtable, etc. Your 'b' statement is incorrect. In both cases, the data is allocated where the struct/class is allocated. Just classes are usually on the heap, structs are generally on the stack. - Gregor Richards
May 28 2007
Gregor Richards Wrote:Martin wrote:Yes, I know that - still, formally they are two different things (albeit very similar).Inspired by the recent discussion about iterator structs/classes I wanted to ask - what's the design rationale behind having both structs and classes? In C++ the necessity was given by backwards compatibility but that doesn't apply to D of course. The only principal differences I can see (I'm not a D programmer (yet), so please correct me if I'm wrong) are a) that structs don't contain run-time meta information (a pointer to a vtable or however that works) and b) that struct variables are statically allocated as opposed to class variables which always seem to be pointers into dynamic memory. Somehow this looks really unorthogonal to me. Especially b) I find strange, can somebody explain the reason for this? cheers MartinFirstly, your assertion about C++ is incorrect. C++ doesn't have both, classes are just structs that are private by default, structs are just classes that are public by default.Structs in D are very light-weight. A struct is just a conglomeration of data. Passing a struct which contains two ints is exactly like passing the two ints, but syntactically less gross. Functions defined within aIsn't that the same as a tuple, then?struct are basically syntactic sugar around functions that are defined taking the struct as the first argument.Hmmm, but in principle the same holds for class functions. The only difference is that there is an additional lookup rule since they are virtual per default.Classes are properly object oriented: They have hierarchies, methods are virtual, etc. As such, they're (comparably to structs) heavyweight: They have classinfo, are allocated on the heap, method calls require looking in a vtable, etc.There is no reason why structs couldn't have hierarchies as well.Your 'b' statement is incorrect. In both cases, the data is allocated where the struct/class is allocated. Just classes are usually on the heap, structs are generally on the stack.Oh, then I got that wrong. I thought there was no way in D to create a class variable on the stack. Anyways, my point is that really the only *necessary* difference between structs and classes is that the latter can have run-time type information and virtual functions. Everything else is just convenient syntactical sugar for which there is no technical reason to not add it to structs as well. And if that's the case I start to wonder if it's not possible to unify the two concepts somehow. cheers Martin
May 28 2007
On Mon, 28 May 2007 17:36:51 -0400, Martin wrote:Anyways, my point is that really the only *necessary* difference between structs and classes is that the latter can have run-time type information and virtual functions. Everything else is just convenient syntactical sugar for which there is no technical reason to not add it to structs as well. And if that's the case I start to wonder if it's not possible to unify the two concepts somehow.They cannot and should not be 'unified' because their purpose is different. They serve different roles for the programmer. To quote the D documentation "Structs are meant as simple aggregations of data, or as a way to paint a data structure over hardware or an external type." Class objects contain at least two hidden data members which mean that they cannot be used to 'paint over RAM', to give structure to some data. See the ABI section of the docs ... An object consists of: --------*------------------ offset | contents --------+------------------ 0 | pointer to vtable ptrsize | monitor In other words an 'empty' object takes up 8 bytes (on a 32-bit machine) and an empty struct takes up zero bytes. -- Derek Parnell Melbourne, Australia "Justice for David Hicks!" skype: derek.j.parnell
May 28 2007
Derek Parnell Wrote:On Mon, 28 May 2007 17:36:51 -0400, Martin wrote:I know, but the differences between structs and classes go far beyond that. In my opinion that wouldn't be necessary. Or put the other way around I think it would be much more elegant (and make D easier to learn) to have aggregate types, RTTI and value/reference semantics as three orthogonal concepts. C++ does that by using virtual vs. the default and pointers/references vs. values with all the associated problems but there might be a cleaner and nicer way without having to give up the flexibility.Anyways, my point is that really the only *necessary* difference between structs and classes is that the latter can have run-time type information and virtual functions. Everything else is just convenient syntactical sugar for which there is no technical reason to not add it to structs as well. And if that's the case I start to wonder if it's not possible to unify the two concepts somehow.They cannot and should not be 'unified' because their purpose is different. They serve different roles for the programmer. To quote the D documentation "Structs are meant as simple aggregations of data, or as a way to paint a data structure over hardware or an external type." Class objects contain at least two hidden data members which mean that they cannot be used to 'paint over RAM', to give structure to some data. See the ABI section of the docs ... An object consists of: --------*------------------ offset | contents --------+------------------ 0 | pointer to vtable ptrsize | monitor In other words an 'empty' object takes up 8 bytes (on a 32-bit machine) and an empty struct takes up zero bytes. -- Derek Parnell Melbourne, Australia "Justice for David Hicks!" skype: derek.j.parnell
May 29 2007
Martin wrote:C++ does that by using virtual vs. the default and pointers/references vs. values with all the associated problems but there might be a cleaner and nicer way without having to give up the flexibility.That is why C++ sucks. I actually like the D solution .. specially having used Java before .. a language with NOTHING other than classes!! and C++ .. a language without "real" classes. D has the best "in the middle" solution.
May 29 2007
Martin wrote:There is no reason why structs couldn't have hierarchies as well.When you want POD (plain old data) objects, with or without methods to manipulate them, it is nice to not have the overhead associated with classes. It also would be a bit cumbersome to interface with C code if structs had all of the class overhead.Your 'b' statement is incorrect. In both cases, the data is allocated where the struct/class is allocated. Just classes are usually on the heap, structs are generally on the stack.Oh, then I got that wrong. I thought there was no way in D to create a class variable on the stack. Anyways, my point is that really the only *necessary* difference between structs and classes is that the latter can have run-time type information and virtual functions. Everything else is just convenient syntactical sugar for which there is no technical reason to not add it to structs as well. And if that's the case I start to wonder if it's not possible to unify the two concepts somehow.
May 28 2007
Mike Parker wrote:Martin wrote:In c++ if you define a class without any virtual it effectively becomes a D struct, without the overhead. D takes this one step further I guess and allows the user enforce no virtuals. (Of course the other difference is that classes are passed by reference in D).There is no reason why structs couldn't have hierarchies as well.When you want POD (plain old data) objects, with or without methods to manipulate them, it is nice to not have the overhead associated with classes. It also would be a bit cumbersome to interface with C code if structs had all of the class overhead.Your 'b' statement is incorrect. In both cases, the data is allocated where the struct/class is allocated. Just classes are usually on the heap, structs are generally on the stack.Oh, then I got that wrong. I thought there was no way in D to create a class variable on the stack. Anyways, my point is that really the only *necessary* difference between structs and classes is that the latter can have run-time type information and virtual functions. Everything else is just convenient syntactical sugar for which there is no technical reason to not add it to structs as well. And if that's the case I start to wonder if it's not possible to unify the two concepts somehow.
May 28 2007
Martin wrote:Gregor Richards Wrote:And you can tell they're considered different things by the annoying fact that if you forward declare a type with the wrong one, the C++ compiler will generate an error. ----- class Foobulator; inline void function(Foobulator& fref) { . . . } ----- struct Foobulator { . . . }; ----- ==> Error Foobulator was declared as a class now it's a struct. grrr. I don't care which it is Mr. silly compiler! And you shouldn't either! All you need to know is that I can make a pointer to the darned thing! --bbMartin wrote:Yes, I know that - still, formally they are two different things (albeit very similar).Inspired by the recent discussion about iterator structs/classes I wanted to ask - what's the design rationale behind having both structs and classes? In C++ the necessity was given by backwards compatibility but that doesn't apply to D of course. The only principal differences I can see (I'm not a D programmer (yet), so please correct me if I'm wrong) are a) that structs don't contain run-time meta information (a pointer to a vtable or however that works) and b) that struct variables are statically allocated as opposed to class variables which always seem to be pointers into dynamic memory. Somehow this looks really unorthogonal to me. Especially b) I find strange, can somebody explain the reason for this? cheers MartinFirstly, your assertion about C++ is incorrect. C++ doesn't have both, classes are just structs that are private by default, structs are just classes that are public by default.
May 29 2007
Bill Baxter wrote:Martin wrote:(No, but a non-C++ compiler might...)Gregor Richards Wrote:And you can tell they're considered different things by the annoying fact that if you forward declare a type with the wrong one, the C++ compiler will generate an error.Martin wrote:Yes, I know that - still, formally they are two different things (albeit very similar).Inspired by the recent discussion about iterator structs/classes I wanted to ask - what's the design rationale behind having both structs and classes? In C++ the necessity was given by backwards compatibility but that doesn't apply to D of course. The only principal differences I can see (I'm not a D programmer (yet), so please correct me if I'm wrong) are a) that structs don't contain run-time meta information (a pointer to a vtable or however that works) and b) that struct variables are statically allocated as opposed to class variables which always seem to be pointers into dynamic memory. Somehow this looks really unorthogonal to me. Especially b) I find strange, can somebody explain the reason for this? cheers MartinFirstly, your assertion about C++ is incorrect. C++ doesn't have both, classes are just structs that are private by default, structs are just classes that are public by default.----- class Foobulator; inline void function(Foobulator& fref) { . . . } ----- struct Foobulator { . . . }; ----- ==> Error Foobulator was declared as a class now it's a struct. grrr. I don't care which it is Mr. silly compiler! And you shouldn't either! All you need to know is that I can make a pointer to the darned thing!I know of only one compiler which fails to compile that, and it's a bug. It's perfectly valid C++ code, and has been for a long, long time. class Foobulator; is *exactly* equivalent to struct Foobulator; in standard C++. (Note the semi-colons on there, making these non-definitions.) -- James
May 29 2007
James Dennett wrote:Bill Baxter wrote:Hmm. Would that compiler be Microsoft Visual C++ 6.0?Martin wrote:(No, but a non-C++ compiler might...)Gregor Richards Wrote:And you can tell they're considered different things by the annoying fact that if you forward declare a type with the wrong one, the C++ compiler will generate an error.Martin wrote:Yes, I know that - still, formally they are two different things (albeit very similar).Inspired by the recent discussion about iterator structs/classes I wanted to ask - what's the design rationale behind having both structs and classes? In C++ the necessity was given by backwards compatibility but that doesn't apply to D of course. The only principal differences I can see (I'm not a D programmer (yet), so please correct me if I'm wrong) are a) that structs don't contain run-time meta information (a pointer to a vtable or however that works) and b) that struct variables are statically allocated as opposed to class variables which always seem to be pointers into dynamic memory. Somehow this looks really unorthogonal to me. Especially b) I find strange, can somebody explain the reason for this? cheers MartinFirstly, your assertion about C++ is incorrect. C++ doesn't have both, classes are just structs that are private by default, structs are just classes that are public by default.----- class Foobulator; inline void function(Foobulator& fref) { . . . } ----- struct Foobulator { . . . }; ----- ==> Error Foobulator was declared as a class now it's a struct. grrr. I don't care which it is Mr. silly compiler! And you shouldn't either! All you need to know is that I can make a pointer to the darned thing!I know of only one compiler which fails to compile that, and it's a bug. It's perfectly valid C++ code, and has been for a long, long time.class Foobulator; is *exactly* equivalent to struct Foobulator; in standard C++. (Note the semi-colons on there, making these non-definitions.)Hey, you're right! I just tried it out in gcc. Works fine. And works for MSVC.NET 2003 too. And DMC too! Imagine that. I'll go sit in a corner now. --bb
May 29 2007
Bill Baxter wrote:James Dennett wrote:You named that tune in one.Bill Baxter wrote:Hmm. Would that compiler be Microsoft Visual C++ 6.0?Martin wrote:(No, but a non-C++ compiler might...)Gregor Richards Wrote:And you can tell they're considered different things by the annoying fact that if you forward declare a type with the wrong one, the C++ compiler will generate an error.Martin wrote:Yes, I know that - still, formally they are two different things (albeit very similar).Inspired by the recent discussion about iterator structs/classes I wanted to ask - what's the design rationale behind having both structs and classes? In C++ the necessity was given by backwards compatibility but that doesn't apply to D of course. The only principal differences I can see (I'm not a D programmer (yet), so please correct me if I'm wrong) are a) that structs don't contain run-time meta information (a pointer to a vtable or however that works) and b) that struct variables are statically allocated as opposed to class variables which always seem to be pointers into dynamic memory. Somehow this looks really unorthogonal to me. Especially b) I find strange, can somebody explain the reason for this? cheers MartinFirstly, your assertion about C++ is incorrect. C++ doesn't have both, classes are just structs that are private by default, structs are just classes that are public by default.----- class Foobulator; inline void function(Foobulator& fref) { . . . } ----- struct Foobulator { . . . }; ----- ==> Error Foobulator was declared as a class now it's a struct. grrr. I don't care which it is Mr. silly compiler! And you shouldn't either! All you need to know is that I can make a pointer to the darned thing!I know of only one compiler which fails to compile that, and it's a bug. It's perfectly valid C++ code, and has been for a long, long time.This corner's taken, I banished myself here after posting something naive on a SQLite mailing list earlier... -- Jamesclass Foobulator; is *exactly* equivalent to struct Foobulator; in standard C++. (Note the semi-colons on there, making these non-definitions.)Hey, you're right! I just tried it out in gcc. Works fine. And works for MSVC.NET 2003 too. And DMC too! Imagine that. I'll go sit in a corner now.
May 29 2007
Martin wrote:Inspired by the recent discussion about iterator structs/classes I wanted to ask - what's the design rationale behind having both structs and classes? [...]The most important difference is that structs have value semantics and classes have reference semantics. There are very good reasons to have both, and unifying them would be as wrong as taking away pointers or taking away stack objects. Dave
May 28 2007
David B. Held Wrote:Martin wrote:I totally agree that both are needed, but is it necessary to tie the difference to the difference between structs and classes? It would be nice if I could decide on the spot (i.e. when declaring a variable) in which way to use my type.Inspired by the recent discussion about iterator structs/classes I wanted to ask - what's the design rationale behind having both structs and classes? [...]The most important difference is that structs have value semantics and classes have reference semantics. There are very good reasons to have both, and unifying them would be as wrong as taking away pointers or taking away stack objects.
May 29 2007
Martin wrote:David B. Held Wrote:Unfortunately, you can't decide "on the spot" whether to use polymorphism or dynamic dispatch (nor can you make this choice on a per-instance basis in any other language I know of). The best you can do is get reference semantics for your structs by using 'ref'. But you will never get exact value semantics for classes because that could lead to slicing, which is why classes/structs in C++ are dangerous. However, you can simulate polymorphic value types by creating invariant classes. If you want to create both struct and class versions of your type and select them on a per-instance basis, you can create a template, but that doesn't make a whole lot of sense to me, so I'm not sure when or why you would do that. DaveMartin wrote:I totally agree that both are needed, but is it necessary to tie the difference to the difference between structs and classes? It would be nice if I could decide on the spot (i.e. when declaring a variable) in which way to use my type.Inspired by the recent discussion about iterator structs/classes I wanted to ask - what's the design rationale behind having both structs and classes? [...]The most important difference is that structs have value semantics and classes have reference semantics. There are very good reasons to have both, and unifying them would be as wrong as taking away pointers or taking away stack objects.
May 29 2007
David B. Held Wrote:Martin wrote:But if I understand it correctly the only points where problems can occur are in casts. This means that it should be possible to implement safeguards since for a value the type has to be known at compile time anyways whereas a reference will have RTTI. In both cases it's possible (either for the compiler or the run-time) to determine whether the cast is valid. The only reason why C++ fails miserably in this is that per default it just doesn't care about run-time stuff so every check for validity is up to the (potentially lazy) programmer. In D it would be perfectly possible to make a hybrid reference/value system failsafe. So, you could take a struct value and convert it into a class reference (probably by internally creating an object and filling it with values from the struct) and vice versa. Of course you wouldn't call it struct and class but just values and references of the same type. Note that there would be no reason to abandon the PODness of structs, when making a struct value from a class reference you'd just abandon the meta-info. I think that would simplify matters considerably. I might be totally off here but from what I've read in the docs and on the mailing list it looked to me as if the implementations of structs and classes in the compiler are at least to some degree a parallel effort. In any case, from the user's perspective I find the differences and the resulting restrictions on structs quite unintuitive and arbitrary.David B. Held Wrote:Unfortunately, you can't decide "on the spot" whether to use polymorphism or dynamic dispatch (nor can you make this choice on a per-instance basis in any other language I know of). The best you can do is get reference semantics for your structs by using 'ref'. But you will never get exact value semantics for classes because that could lead to slicing, which is why classes/structs in C++ are dangerous. However, you can simulate polymorphic value types by creating invariant classes. If you want to create both struct and class versions of your type and select them on a per-instance basis, you can create a template, but that doesn't make a whole lot of sense to me, so I'm not sure when or why you would do that. DaveMartin wrote:I totally agree that both are needed, but is it necessary to tie the difference to the difference between structs and classes? It would be nice if I could decide on the spot (i.e. when declaring a variable) in which way to use my type.Inspired by the recent discussion about iterator structs/classes I wanted to ask - what's the design rationale behind having both structs and classes? [...]The most important difference is that structs have value semantics and classes have reference semantics. There are very good reasons to have both, and unifying them would be as wrong as taking away pointers or taking away stack objects.
May 29 2007
Martin wrote:[...] But if I understand it correctly the only points where problems can occur are in casts. This means that it should be possible to implement safeguards since for a value the type has to be known at compile time anyways whereas a reference will have RTTI. [...]I guess my problem is lack of motivation. I'm just not seeing the use cases you are, so I don't see this part of the design space as lacking. Can you show us where you would like to use this feature and how it is better than the way things are now? Dave
May 29 2007