Why can't structs be derived from?

Caligo iteronvexor at gmail.com
Tue Mar 15 09:28:07 PDT 2011


On Tue, Mar 15, 2011 at 10:00 AM, Jonathan M Davis <jmdavisProg at gmx.com>wrote:

> On Tuesday 15 March 2011 06:25:13 Jens wrote:
> > It seems rather fundamental to be able to compose a new struct from a
> > given struct using inheritance. Why is this not allowed?
> >
> > struct slist_node
> > {
> >     slist_node* next;
> > };
> >
> > template <class T>
> > struct slist_node<T>: public slist_node
> > {
> >     T data;
> > };
>
> Classes are polymorphic. Structs are not. This is by design. One of the
> major
> reasons for this is slicing. In C++, if you have a pointer to an object,
> the
> pointer can be of a base type or of the same type as what is pointed to.
> You
> don't necessarily care. The correct code is called polymorphically. When
> you
> assign it to another pointer, it works just fine. You can even safely
> assign it
> to a pointer of a base type.
>
> class A {}
> class B : public A {}
>
> A* a = new B();
> B* b = new B();
>
> You can do the same in D with classes and references (and pointers, except
> that
> pointers aren't polymorphic in D). However, what happens if the type is on
> the
> stack directly?
>
> A a = *(new B());
> B b = *(new B());
>
> Your object just got sliced ( http://en.wikipedia.org/wiki/Object_slicing).
> When it's on the stack, the compiler must know _exactly_ what type of
> object it
> is. That means that you can't have it be a different type than what you say
> it
> is. And that means that while assigning a B to a B works just fine,
> assigning a B
> to an A means that all the parts of that object that are B-specific, get
> lost.
> Only the parts that are part of an A get copied (since you just assigned it
> to
> an A). Take
>
> class A
> {
>    int x;
> }
>
> class B : public A
> {
>    int y;
>    float z;
> }
>
> An A has an int in it. A B has an additional y and z in it. When you assign
> a B
> to an A, the y and z variables get lost. In many cases, this results in a
> completely invalid object and is _rarely_ what you really want. If you're
> not
> careful, this can be a big problem in C++. In C++, you _must_ use pointers
> if
> you want polymorphism. This also means that you generally avoid assigning
> dereferenced pointers to stack variables.
>
> D's solution is to make it so that there is a clear separation between non-
> polymorphic types on the stack and polymorphic types on the heap. Structs
> have
> no polymorphism and no inheritance. They live on th stack. Classes do have
> polymorphism nad ihneritance. They live on the heap. You _can_ have
> pointers to
> structs, but they're still non-polymorphic, and you can't normally stick a
> class
> on the stack.
>
> There are other benefits to making structs non-polymorphic (such as not
> needing a
> virtual table), but the main one is to avoid the slicing issue. Overall, it
> works quite well. One of the major, potential sources of bugs in C++ is
> completely avoided in D.
>
> - Jonathan M Davis
>



struct MyStruct{

  MyClass mc;  // 4 bytes
  int a;
  int b;
  char c;
}

class MyClass{

  MyStruct ms;  // 16 bytes
  int x;
  int y;
  char z;
}


so, 'ms' is on the heap, even though it's a struct, right?  but 'mc' is just
a reference and lives on the stack, and that's why it's only 4 bytes?

btw, coming from C++, I find 'MyClass mc;' and 'MyStruct ms;' confusing; one
is a reference and the other isn't.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20110315/ddff0781/attachment.html>


More information about the Digitalmars-d mailing list