classes structs

Jonathan M Davis jmdavisProg at gmx.com
Sat Sep 15 03:58:50 PDT 2012


On Saturday, September 15, 2012 00:19:07 David Currie wrote:
> At the risk of appearing ignorant, I don't know everything about
> D.
> However in D I have noticed the following.
> 
> It is a policy decision in D that a class is ALWAYS on the heap
> and passed
> by REFERENCE. (I know there is a keyword to put a class object on
> the stack
> but this is not facile and needing a workaround is poor language
> design).
> This is effectively FORCED Java.
> A D struct is on the stack and is NOT a class and has NO
> inheritance.
> 
> I have issues with this philosophy.
> 
> It seems FUNDAMENTAL to me that a programmer needs both stack and
> heap
> objects and should KNOW when to use each and should ALWAYS have a
> choice.
> 
> ALL struct VARIABLES when declared are initialised to their .init
> value.
> Just in case a programmer "forgets" to initialize them.
> This is like using a sledgehammer instead of a scalpel.
> Could you answer me WHY??
> ALL classes when declared are instantiated on the heap
> and their constructor called. Again I ask WHY??
> 
> Why can't the programmer have the freedom to build his own objects
> when he wants to with the compiler advising of errors ?
> 
> Of course I have more to say about this but I need answers to
> these questions
> to proceed.

Classes are polymorphic. They have inheritance and virtual functions. 
Polymorphism makes no sense with a variable on the stack. Having inheritance 
with objects on the stack risks object slicing ( 
http://en.wikipedia.org/wiki/Object_slicing ). Sure, you _can_ have a 
polymorphic object which is on the stack (which is why C++ allows classes on 
the stack and why D has std.typecons.scoped), but it's the sort of thing that 
tends to be begging for bugs.

The designers of D decided that it's was cleaner and safer to separate objects 
which were meant to be polymorphic and those which were meant to be non-
polymorphic (as is often considered best practice in C++), and since having 
polymorphic objects means that you're not using their polymorphism and having 
them on the stack can be dangerous, it was decided to follow Java and C#'s 
example and make all classes into reference types which live on the heap 
(though unlike Java and C#, we _can_ put such objects on the stack if we 
really want to via std.typecons.scoped). But unlike Java and C#, we have 
structs which are full-on objects with constructors and destructors and are 
the same in classes in pretty much every way except that they have no 
polymorphism and normally go on the stack.

The result is safer than what C++ has but is still very powerful. And since 
it's arguably best practice not to put objects which are meant to use 
polymorphism on the stack in C++ anyway, it's not even really restricting you 
from much in comparison to C++ (and std.typecons.scoped makes it possible to 
put classes on the stack if you really want to, making the restrictions even 
less).

You can like it or not, but separating structs and classes and making classes 
reference types on the heap is a design decision based on the best practices 
and common bugs in C++. And it works very well. Upon occasion, it can be 
limiting (hence why we have std.typecons.scoped), but I don't think that 
you're going to find very many D programmers who think that the separation of 
structs and classes was a bad idea.

- Jonathan M Davis


More information about the Digitalmars-d mailing list