Hiding class pointers -- was it a good idea?

Bill Baxter dnewsgroup at billbaxter.com
Wed Aug 15 10:09:54 PDT 2007


Deewiant wrote:
> Bill Baxter wrote:
>> In large part it all stems from the decision to make classes and structs
>> different.  That seems nice in theory, but as time goes on the two are
>> becoming more and more alike.  Classes can now be stack-allocated with
>> scope.  Structs are supposedly going to get constructors, and maybe even
>> destructors.  It kind of makes me think that maybe separating structs
>> and classes was a bad idea.  I have yet to ever once say to myself
>> "thank goodness structs and classes are different in D!", though plenty
>> of times I've muttered "dangit why can't I just get a default copy
>> constructor for this class" or "shoot, these static opCalls are
>> annoying" or "dang, I wish I could get a weak reference to a struct", etc.
>>
> 
> I think the separation was a good idea. I like structs not having hidden fields,
> being laid out in memory exactly as I write the code, and having no performance
> overhead due to vtables, etc. 

Well, in C++ you only get those things if you declare one or more 
functions as virtual.  D automates flagging functions with 'virtual', so 
you couldn't do the same thing in D.  But you could imagine a D with a 
'nonvirtual' keyword that if stuck into a class would make it POD.

> In C++, the only difference is that structs
> default to public while classes default to private. Where's the use in that?

Very little point in it, I agree.  C++ could have just stuck with 
'struct' and been just fine.  Part of my point was that maybe we didn't 
really need two different things in D either.

> Just use a class for everything - and most people do. I like my POD datatype,
> thank you very much.

I like my POD datatypes too.  And I like the fact that in C++ I can 
change from POD to not-POD by adding one little word to the class/struct 
("virtual").  Almost all code that relies on that POD type will still 
work if it gains a vtable and one or more virtual methods.  In D it's 
much more difficult.  static opCalls need to be changed to this() 
constructors, and every bit of code that uses the thing will have to be 
changed -- mostly Foo*'s will need to be changed to Foo's.  But some 
places may be better off changing to scope Foo.  So you need to look 
closely at the code you're changing.

> With that said, I agree that hiding class pointers may not have been a good
> idea. Still, I can't think of many points which would make it a particularly bad
> idea.

I guess the main down side is just the inconsistency of value/ptr usages 
--  Foo/Foo* on the one hand and scope Foo/Foo on the other.  It's easy 
to get used to lack of pointers in Java because it's consistent.  But in 
D you have to go back and forth between C-like and Java-like 
line-by-line in your code.

Put it this way, if I download someone's container library, I don't want 
to have to think about whether their CoolSet is a class or a struct in 
order to create one by value.  Note that built-in containers are 
basically struct-like, so in some ways it makes sense for user defined 
containers to be structs, too.  And C++ STL containers are almost always 
used by-value (i.e. you almost never see "new std::vector()").  But on 
the other hand a container may want to use interfaces or inheritance in 
the implementation, and writing static opCalls is just a pain, so it 
also also makes sense to use a class.  The fact that it could reasonably 
be either class or struct means there's one more bit of information I 
have to keep in mind for every user-defined type in my code.

> Defaulting to stack allocation somehow would be better: it's easy to write
> "auto" instead of "scope" and forget about it. But then, the performance in such
> cases rarely matters, and when it does, you do notice such things because you're
> looking for them.

I don't think the performance is as much of an issue as consistency.

--bb



More information about the Digitalmars-d mailing list