<br><br><div class="gmail_quote">On Tue, Mar 15, 2011 at 10:00 AM, Jonathan M Davis <span dir="ltr"><<a href="mailto:jmdavisProg@gmx.com">jmdavisProg@gmx.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div><div></div><div class="h5">On Tuesday 15 March 2011 06:25:13 Jens wrote:<br>
> It seems rather fundamental to be able to compose a new struct from a<br>
> given struct using inheritance. Why is this not allowed?<br>
><br>
> struct slist_node<br>
> {<br>
>     slist_node* next;<br>
> };<br>
><br>
> template <class T><br>
> struct slist_node<T>: public slist_node<br>
> {<br>
>     T data;<br>
> };<br>
<br>
</div></div>Classes are polymorphic. Structs are not. This is by design. One of the major<br>
reasons for this is slicing. In C++, if you have a pointer to an object, the<br>
pointer can be of a base type or of the same type as what is pointed to. You<br>
don't necessarily care. The correct code is called polymorphically. When you<br>
assign it to another pointer, it works just fine. You can even safely assign it<br>
to a pointer of a base type.<br>
<br>
class A {}<br>
class B : public A {}<br>
<br>
A* a = new B();<br>
B* b = new B();<br>
<br>
You can do the same in D with classes and references (and pointers, except that<br>
pointers aren't polymorphic in D). However, what happens if the type is on the<br>
stack directly?<br>
<br>
A a = *(new B());<br>
B b = *(new B());<br>
<br>
Your object just got sliced ( <a href="http://en.wikipedia.org/wiki/Object_slicing" target="_blank">http://en.wikipedia.org/wiki/Object_slicing</a> ).<br>
When it's on the stack, the compiler must know _exactly_ what type of object it<br>
is. That means that you can't have it be a different type than what you say it<br>
is. And that means that while assigning a B to a B works just fine, assigning a B<br>
to an A means that all the parts of that object that are B-specific, get lost.<br>
Only the parts that are part of an A get copied (since you just assigned it to<br>
an A). Take<br>
<br>
class A<br>
{<br>
    int x;<br>
}<br>
<br>
class B : public A<br>
{<br>
    int y;<br>
    float z;<br>
}<br>
<br>
An A has an int in it. A B has an additional y and z in it. When you assign a B<br>
to an A, the y and z variables get lost. In many cases, this results in a<br>
completely invalid object and is _rarely_ what you really want. If you're not<br>
careful, this can be a big problem in C++. In C++, you _must_ use pointers if<br>
you want polymorphism. This also means that you generally avoid assigning<br>
dereferenced pointers to stack variables.<br>
<br>
D's solution is to make it so that there is a clear separation between non-<br>
polymorphic types on the stack and polymorphic types on the heap. Structs have<br>
no polymorphism and no inheritance. They live on th stack. Classes do have<br>
polymorphism nad ihneritance. They live on the heap. You _can_ have pointers to<br>
structs, but they're still non-polymorphic, and you can't normally stick a class<br>
on the stack.<br>
<br>
There are other benefits to making structs non-polymorphic (such as not needing a<br>
virtual table), but the main one is to avoid the slicing issue. Overall, it<br>
works quite well. One of the major, potential sources of bugs in C++ is<br>
completely avoided in D.<br>
<font color="#888888"><br>
- Jonathan M Davis<br>
</font></blockquote></div><br><br><br>struct MyStruct{<br><br>  MyClass mc;  // 4 bytes<br>  int a;<br>  int b;<br>  char c;<br>}<br><br>class MyClass{<br><br>  MyStruct ms;  // 16 bytes<br>  int x;<br>  int y;<br>  char z;<br>
}<br><br><br>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?<br><br>btw, coming from C++, I find 'MyClass mc;' and 'MyStruct ms;' confusing; one is a reference and the other isn't.  <br>