-betterC and extern(C++) classes

Moritz Maxeiner via Digitalmars-d digitalmars-d at puremagic.com
Sun Sep 10 09:48:06 PDT 2017


On Sunday, 10 September 2017 at 15:12:12 UTC, Yuxuan Shui wrote:
> On Sunday, 10 September 2017 at 14:42:42 UTC, Moritz Maxeiner 
> wrote:
>> On Sunday, 10 September 2017 at 14:04:20 UTC, rikki cattermole 
>> wrote:
>>> On 10/09/2017 2:19 PM, Moritz Maxeiner wrote:
>>>> If TypeInfo for extern(C++) classes is removed, couldn't 
>>>> final extern(C++) classes without base class and which don't 
>>>> implement any interfaces omit the vtable so that the 
>>>> following assert holds:
>>>> 
>>>> ---
>>>> final extern(C++) class Foo {}
>>>> static assert (__traits(classInstanceSize, Foo) == 0LU);
>>>> ---
>>>> 
>>>> The reason I ask is that fairly often I have an abstraction 
>>>> that's better suited as a reference type than a value type, 
>>>> but doesn't need any runtime polymorphy (or the monitor 
>>>> standard classes have). Structs + pointers are the only way 
>>>> I know of to avoid the (in this special case) unneeded 
>>>> vtable overhead, but it always ends up looking worse to read.
>>>
>>> We can do it for any class if its final.
>>
>> Even final classes can always inherit (potentially already 
>> overridden) virtual methods from their parent classes and 
>> since all normal D classes inherit from core.object : Object 
>> [1], which defines virtual methods (`toString`, `toHash`, 
>> `opCmp, and `opEquals`), I don't see how this can be true.
>
> With a final class reference, we always know what function to 
> call at compile time (since it can't be inherited). Therefore 
> we don't need a vtable.

---
class Base
{
     string name()
     {
         return "Base";
     }
}

class ChildA : Base
{
     override string name()
     {
         return "ChildA";
     }
}

final class ChildB : Base
{
     override string name()
     {
         return "ChildB";
     }
}

void foo(Base b)
{
     import std.stdio;
     b.name.writeln;
}

void main(string[] args)
{
     Base b;
     if (args.length > 1) b = new ChildA;
     else b = new ChildB;
     b.foo();
}
---

It is not known at compile time which class `foo`'s parameter `b` 
will actually be an instance of (Base, ChildA, or ChildB), so 
static dispatch is not possible; it requires dynamic dispatch. 
Since dynamic dispatch for classes is done in D via vtables, 
ChildB needs a vtable.


More information about the Digitalmars-d mailing list