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