extern(C++) multiple inheritence
Manu via Digitalmars-d
digitalmars-d at puremagic.com
Mon Jan 18 21:10:19 PST 2016
I'm repeating this here from the depths of my prior whinge thread,
since this is kind of a new topic.
D's multiple inheritance solution is single-inheritance + interfaces.
Rightly so, it's a great solution, and this matches what all the C++
programmers I've ever worked with do anyway. Trouble is, it doesn't
seem to work with extern(C++) at the moment.
Note: this is my current hard-blocker. I can't progress without this.
Situation:
-------------------
In C++:
class Base
{
virtual ~Base() {}
size_t x;
};
class Interface
{
virtual void A() = 0;
virtual void B() = 0;
virtual void C() = 0;
virtual void Method() = 0;
};
class Derived : public Base, public Interface
{
size_t y;
};
-------------------
D:
extern(C++) class Base
{
~this() {}
size_t x;
}
extern(C++) interface Interface
{
void A();
void B();
void C();
void Method();
}
extern(C++) class Derived : Base, Interface
{
size_t y;
}
-------------------
This code should work.
In C++, Derived is laid out:
{
void *__Base_vtable;
size_t x;
void *__Interface_vtable;
size_t y;
}
This is as I expect.
In D, according to the debuginfo output by DMD, Derived is reported as:
{
void *__Base_vtable;
size_t x;
size_t y;
}
* The actual binary may not match the debuginfo; I didn't check, but
there is some evidence for this.
Surprisingly, this compiles, but calling Method generates wrong code:
00007FF72DB7381B mov rbx,qword ptr [this]
00007FF72DB7381F mov rcx,qword ptr [rbx+10h] // rcx is now
__Interface_vtable!
00007FF72DB73823 mov rcx,qword ptr [rcx]
00007FF72DB73826 sub rsp,20h
00007FF72DB7382A mov rax,qword ptr [rcx]
00007FF72DB7382D call qword ptr [rax+18h] // 18h is the
offset of Method, rax is wrong. [[rbx+10h]+18h] is the correct call.
We load rbx = [this], then we load rcx = [rbx+10h]. This looks good,
[rbx+10h] is the correct offset of __Interface_vtable in C++, even
though the debuginfo claims that's the offset of 'y'.
Then it gets weird; rcx = [rcx], this is effectively getting the first
function pointer in the vtable; A().
Then further compounding with rax = [rcx], loading the first 8 bytes
of program code from the function A()!
Finally it calls [rax+18h]. If rax were still __Interface_vtable, 18h
is the correct offset of the function I'm calling (Method), and it was
correct after the second opcode, but those 2 weird dereferences broke
it.
Hoping this can be supported, I can't move forward without this.
More information about the Digitalmars-d
mailing list