what was wrong with struct & class in C++?

Bill Baxter dnewsgroup at billbaxter.com
Sun Dec 16 12:42:49 PST 2007


Bill Baxter wrote:
> Yigal Chripun wrote:
>> Bill Baxter wrote:
>>> Walter Bright wrote:
>>>> Christopher Wright wrote:
>>>>> That would be allowed in D, if you could overload T.opAssign(T).
>>>>
>>>> C++ still has well-known slicing problems, even with overloading 
>>>> assignment.
>>>>
>>>> The question is not "can this be done", it's more "is there a 
>>>> compelling reason to support such behavior". I think the answer is 
>>>> no. Do you really want a language where a class designer feels 
>>>> compelled to define an opassign overload, then make it private to 
>>>> prevent people from using the class as a value type? Where the base 
>>>> class designer needs to know what the derived classes are doing so 
>>>> he can make the destructor virtual or not? Where you cannot have 
>>>> arrays of base classes?
>>>
>>> At least C++ lets you control copying behavior completely in all 
>>> circumstances.  And documents what you are supposed to do clearly. 
>>> Right now D gives you the choice of
>>>
>>> 1) [structs] copy by value only, with no option to customize or 
>>> intercept copy operations
>>> 2) [classes] no defined copy behavior whatsoever
>>>
>>> 1) makes interesting ref counting wrappers etc impossible, but I 
>>> think you're planning to fix that one.
>>>
>>> I think 2) is a problem also.  It means that developers will each 
>>> come up with their own way to copy objects because there's no clear 
>>> way to do it.  I think some particular scheme should be crowned, like 
>>> any class that wants to be copyable should provide a the pair of 
>>> methods dup(), and copy(ThisType).  And maybe there should be 
>>> something in Object to this effect also, even if they don't do much 
>>> of anything.  Looks like java implements a clone() method in the base 
>>> Object class.  But it looks like that just makes it so you get a 
>>> runtime exception if the class you're trying to clone doesn't support 
>>> cloning.  That doesn't seem like an improvement over a compile time 
>>> error.
>>>
>>> So I'm not really sure what should be done, but I definitely think 
>>> something should be done to specify "the D way" to polymorphically 
>>> copy objects.  Built-ins mostly have .dup properties, but I don't 
>>> think the spec actually says anywhere that user classes that want to 
>>> be copyable should have a .dup.  But even specifying a .dup is not 
>>> enough I think, because if I derive from some class A, I have to 
>>> create my derived class, then get class A to copy the A parts of the 
>>> new object somehow, say via a method like A.copy(A copy_from).
>>>
>>> C++ may have problems regarding copying classes, but D's solution is 
>>> effectively to just remove the C++ functionality good and bad.  Ok 
>>> the slicing problem is gone, but so is copying.  There should be one 
>>> obvious way to make classes in D copyable, whether it be enforced by 
>>> the language, compiler, or simply the spec and D community.
>>>
>>> --bb
>>
>> In java you also need to implement a clonable interface which is a 
>> marker interface.
>> I think that adding a clonable interface to the standard library 
>> should be enough. something like:
>> ---
>> interface clonable {
>>     object dup();
>> }
>> ---
>> now you need to implement it to support copying. 
> 
> Is there really any benefit in making it an interface in D since you can 
> just do a static if check to see if it has a dup method?
> 
>> I don't think a dup method should be added to object. as you said, it 
>> isn't really an improvement, and usually Java experts recommend 
>> avoiding clone().
> 
> What do you mean they recommend avoiding it?  What do they recommend 
> instead?
> 
>> also, i don't see why a copy method is required.
>> for example, check the following code:
>> ---
>> class Base : clonable {
>>     Base dup() {
>>        auto ret = cast(Base) this.classinfo.create;
>>        ret.x = this.x;
>>        ret.y = this.y;
>>        return ret;
>>     }
>>     int x = 6;
>>     double y = 8;
>> }
>>
>> class DerivedA : Base {
>>     override DerivedA dup() {
>>        auto ret = cast(DerivedA) super.dup;
>>        ret.w = this.w;
>>        return ret;
>>     }
>>     long w = 42;
>> }
> 
> Ah ha!  Ok, that's great.  This is exactly what I was looking for over 
> on the thread I started on D.learn ("implementing dup/clone for class 
> hierarchies").   Steven suggested using classinfo.create, but he left 
> his solution using a separate copy() method (or I just misunderstood 
> him), and that just ends up in a lot of casting.  But your method seems 
> to work.

There is one problem with that solution.  classinfo.create only works if 
the object being duplicated has a default constructor.  If you split it 
into dup and copy, then you can have the most derived class create the 
instance, calling whatever constructor it wants to.

I'm not sure why classinfo.create returns null though.  The doc for it 
only says "Create instance of Object represented by 'this'.".  Doesn't 
mention anything about ever returning null.

--bb



More information about the Digitalmars-d mailing list