Thread overview | |||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 24, 2004 why cant structs have base structs | ||||
---|---|---|---|---|
| ||||
This:
struct a {
}
struct b : a {
}
is not valid, the spec does not seem to allow it, why not?
Regan
--
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
|
June 24, 2004 Re: why cant structs have base structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | Regan Heath wrote:
> This:
>
> struct a {
> }
>
> struct b : a {
> }
>
> is not valid, the spec does not seem to allow it, why not?
My guess:
Structs cannot have virtual functions (adding that feature would mean overhead which should be avoided for structs)
Without virtual functions, the behavior of struct-inheritance would be strangely different from the behavior of class-inheritance, where every public function is implicitly virtual.
Furthermore: without polymorphism (which would require virtual functions) inheritance is just a matter of saving some typing. And for that, you can also use mixins.
|
June 24, 2004 Re: why cant structs have base structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Norbert Nemec | On Thu, 24 Jun 2004 07:52:11 +0200, Norbert Nemec <Norbert.Nemec@gmx.de> wrote: > Regan Heath wrote: > >> This: >> >> struct a { >> } >> >> struct b : a { >> } >> >> is not valid, the spec does not seem to allow it, why not? > > My guess: > > Structs cannot have virtual functions (adding that feature would mean > overhead which should be avoided for structs) Agreed. > Without virtual functions, the behavior of struct-inheritance would be > strangely different from the behavior of class-inheritance, where every > public function is implicitly virtual. Different, yes. Strange .. not so long as it's documented. > Furthermore: without polymorphism (which would require virtual functions) > inheritance is just a matter of saving some typing. And for that, you can > also use mixins. Ok. You've convinced me. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/ |
June 24, 2004 Re: why cant structs have base structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | Regan Heath wrote: > On Thu, 24 Jun 2004 07:52:11 +0200, Norbert Nemec <Norbert.Nemec@gmx.de> wrote: > >> Regan Heath wrote: >> >>> This: >>> >>> struct a { >>> } >>> >>> struct b : a { >>> } >>> >>> is not valid, the spec does not seem to allow it, why not? >> >> >> My guess: >> >> Structs cannot have virtual functions (adding that feature would mean >> overhead which should be avoided for structs) > > > Agreed. > >> Without virtual functions, the behavior of struct-inheritance would be >> strangely different from the behavior of class-inheritance, where every >> public function is implicitly virtual. > > > Different, yes. Strange .. not so long as it's documented. > >> Furthermore: without polymorphism (which would require virtual functions) >> inheritance is just a matter of saving some typing. And for that, you can >> also use mixins. > > > Ok. You've convinced me. > but what if you wanted to pass a SuperThing into a function that only took a thing and didn't want to use templates struct Thing{ float amt; } struct SuperThing :Thing { char[] name; } now it's not just a matter of saving typing, but actually having it do all the things you could with thing. in C you'd use an anonymous union to accomplish this-- is that also possible in D? struct Thing { float amt; }; struct SuperThing { union { float amt; Thing thing; }; char[] name; }; > Regan > |
June 24, 2004 Re: why cant structs have base structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Horn | Daniel Horn wrote:
>>> Furthermore: without polymorphism (which would require virtual functions) inheritance is just a matter of saving some typing. And for that, you can also use mixins.
>>
>>
>> Ok. You've convinced me.
>>
> but what if you wanted to pass a SuperThing into a function that only took a thing and didn't want to use templates
That's just what I mean with "polymorphism" - as mentioned: polymorphism demands for virtual functions, and these mean overhead. If you want polymorphism, use classes. (There is no point in using polymorphism without handling the objects by reference, anyway.)
|
June 24, 2004 Re: why cant structs have base structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Norbert Nemec | Norbert Nemec wrote:
> Daniel Horn wrote:
>
>
>>>>Furthermore: without polymorphism (which would require virtual
>>>>functions) inheritance is just a matter of saving some typing. And for
>>>>that, you can also use mixins.
>>>
>>>
>>>Ok. You've convinced me.
>>>
>>
>>but what if you wanted to pass a SuperThing into a function that only
>>took a thing and didn't want to use templates
>
>
> That's just what I mean with "polymorphism" - as mentioned: polymorphism
> demands for virtual functions, and these mean overhead. If you want
> polymorphism, use classes. (There is no point in using polymorphism without
> handling the objects by reference, anyway.)
>
"polymorphism" does not demand for virtual functions by default.
in C++ i could do the following:
struct MyPolyStruct
{
int type;
};
struct A : public MyPolyStruct
{
int a;
}
struct C : public MyPolyStruct
{
float c[1000];
}
void bla(MyPolyStruct* p)
{
switch(p->type)
{
//do stuff
}
}
I still need to do a cast to get the subclass data,
but this is a bit "type-safier" than doing this in D:
template MyPolyType
{
int type;
};
struct Base
{
mixin MyPolyType;
}
struct A
{
mixin MyPolyType;
int a;
}
struct C
{
mixin MyPolyType;
float c[1000];
}
int bla(void* p) // need to use void ptr here
{
switch((cast(Base)p).type)
{
//do stuff
}
}
some times you need to do this stuff, f.e. when you implement functions that work on binary formats. Standard polymorphism doesn't help here at all.
Are there better solutions for doing this kind of stuff in D?
Note that using unions doesn't really help ( without having memory overhead):
struct MyPolyStruct
{
int type;
union
{
int a;
float c[1000];
} data;
};
Jan-Eric
|
June 24, 2004 Re: why cant structs have base structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Horn | Daniel Horn wrote:
> struct Thing{
> float amt;
> }
> struct SuperThing :Thing {
> char[] name;
> }
>
> now it's not just a matter of saving typing, but actually having it do all the things you could with thing.
> in C you'd use an anonymous union to accomplish this-- is that also possible in D?
>
> struct Thing {
> float amt;
> };
>
> struct SuperThing {
> union {
> float amt;
> Thing thing;
> };
> char[] name;
> };
What you code here should work...though I don't know why you wouldn't just include the Thing directly. The union is unnecessary:
struct SuperThing {
Thing thing;
char[] name;
};
If you want to implement something that looks more like C++ inheritance, you can do it with properties:
struct SuperThing {
Thing super;
float amt() { return super.amt; }
float amt(float f) { return super.amt = f; }
char[] name;
};
You don't get implicit casting, but that's not too hard:
Thing* castThing(SuperThing* s) { return s.super; }
Likewise, you can even implement constructors and virtual functions by hand if you want; but you have to run the constructor by hand, and make sure it initialized the virtual functions allright:
struct Thing {
struct {
int delegate() foo;
} vtbl;
void Constructor() {
this.vtbl.foo = &this.foo;
}
int foo() { ...do stuff... }
float amt;
}
struct SuperThing {
Thing super;
float amt() { return super.amt; }
float amt(float f) { return super.amt = f; }
void Constructor() {
super.Constructor();
super.vtbl.foo = &this.foo;
}
int foo() { ...do stuff... }
char[] name;
}
Thing thing1; thing1.Constructor();
SuperThing thing2; thing2.Constructor();
Thing *ptr1;
Thing *ptr2;
ptr1 = &thing1;
ptr2 = castThing(&thing2);
ptr1.vtbl.foo(); // runs Thing.foo()
ptr2.vtbl.foo(); // runs SuperThing.foo()
|
June 24, 2004 Re: why cant structs have base structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russ Lewis | Russ Lewis wrote:
> Daniel Horn wrote:
>
>> struct Thing{
>> float amt;
>> }
>> struct SuperThing :Thing {
>> char[] name;
>> }
>>
>> now it's not just a matter of saving typing, but actually having it do all the things you could with thing.
>> in C you'd use an anonymous union to accomplish this-- is that also possible in D?
>>
>> struct Thing {
>> float amt;
>> };
>>
>> struct SuperThing {
>> union {
>> float amt;
>> Thing thing;
>> };
>> char[] name;
>> };
>
>
> What you code here should work...though I don't know why you wouldn't just include the Thing directly. The union is unnecessary:
>
> struct SuperThing {
> Thing thing;
> char[] name;
> };
>
>
>
> If you want to implement something that looks more like C++ inheritance, you can do it with properties:
>
> struct SuperThing {
> Thing super;
> float amt() { return super.amt; }
> float amt(float f) { return super.amt = f; }
> char[] name;
> };
>
> You don't get implicit casting, but that's not too hard:
>
> Thing* castThing(SuperThing* s) { return s.super; }
>
> Likewise, you can even implement constructors and virtual functions by hand if you want; but you have to run the constructor by hand, and make sure it initialized the virtual functions allright:
>
> struct Thing {
> struct {
> int delegate() foo;
> } vtbl;
>
> void Constructor() {
> this.vtbl.foo = &this.foo;
> }
>
> int foo() { ...do stuff... }
>
> float amt;
> }
>
> struct SuperThing {
> Thing super;
> float amt() { return super.amt; }
> float amt(float f) { return super.amt = f; }
>
> void Constructor() {
> super.Constructor();
> super.vtbl.foo = &this.foo;
> }
>
> int foo() { ...do stuff... }
>
> char[] name;
> }
>
> Thing thing1; thing1.Constructor();
> SuperThing thing2; thing2.Constructor();
>
> Thing *ptr1;
> Thing *ptr2;
>
> ptr1 = &thing1;
> ptr2 = castThing(&thing2);
>
> ptr1.vtbl.foo(); // runs Thing.foo()
> ptr2.vtbl.foo(); // runs SuperThing.foo()
>
that looks like a reasonable solution.
it's not too much work for doing this kind of rare stuff.
with mixins you can do this, too:
struct Thing
{
// stuff
}:
template BaseStruct
{
Thing myThing;
Thing* castThing()
{
return &myThing;
}
};
struct A
{
mixin BaseStruct;
int stuffint;
};
|
June 24, 2004 Re: why cant structs have base structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jan-Eric Duden | Jan-Eric Duden wrote:
> Are there better solutions for doing this kind of stuff in D?
Use classes!
The only reason to use struct instead of class is, if you want value-semantics (as opposed to reference semantics which are the only available behaviour for classes in D)
Polymorphism is generally only possible when handling references. (Since the size of an inheriting class is not known, it cannot be passed by value)
Your C++ example uses a pointer to a struct. In D, you should simply use a class for that.
|
June 24, 2004 Re: why cant structs have base structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Norbert Nemec | Norbert Nemec wrote:
> Jan-Eric Duden wrote:
>
>>Are there better solutions for doing this kind of stuff in D?
>
>
> Use classes!
>
> The only reason to use struct instead of class is, if you want
> value-semantics (as opposed to reference semantics which are the only
> available behaviour for classes in D)
>
> Polymorphism is generally only possible when handling references. (Since the
> size of an inheriting class is not known, it cannot be passed by value)
>
> Your C++ example uses a pointer to a struct. In D, you should simply use a
> class for that.
>
You can't use classes in some cases. With classes you can't model an exact binary layout. With classes you have memory overhead that is too large in some cases.Custom allocators won't help all the time.
A small example: I have a file with 1,000,000 objects. all objects have the same size. I need to do some sorting and other stuff. the object size is 16 bytes. 16 MB is not too much for my memory requirements.
I allocate just one chunk of memory. read all the objects into that chunk. hold a struct pointer on that chunk. easy and efficient.
If I have to do that with class objects... I get gc overhead for 1 million objects, 1 million times a monitor, 1 million times a virtual function table pointer, ... 1 million new calls, 1 million read calls.
In that case structs a just better.
Jan-Eric
|
Copyright © 1999-2021 by the D Language Foundation