www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - C++ linkage specifics WRT virtual vs non-virtual member functions

reply Roman Hargrave <roman hargrave.info> writes:
I'm writing some bindings and have run in to a dilemma due to the 
lack of explicit information on how the D compiler "decides" to 
use virtual dispatch for a member function or not.

Specifically, I have a C++ library that _explicitly_ marks some 
member functions as virtual, in addition to a plethora of 
non-virtual functions.

I would like to be certain that the D compiler understands that I 
would like it to treat those functions as virtual functions, but 
unlike C++ where there is a `virtual` classifier for functions, D 
does not appear to have such a facility.

The C++ interop documentation suggests that both non- and virtual 
functions are supported, but further suggests that it only treats 
inherited functions as virtual with no method of explicitly 
requesting virtual dispatch for that method.

As far as I can tell, all specified member functions in a class 
with C++ linkage are assumed to be non-virtual unless they are 
overriden?
Aug 13 2017
next sibling parent Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
On Sunday, 13 August 2017 at 07:18:31 UTC, Roman Hargrave wrote:
 I'm writing some bindings and have run in to a dilemma due to 
 the lack of explicit information on how the D compiler 
 "decides" to use virtual dispatch for a member function or not.

 Specifically, I have a C++ library that _explicitly_ marks some 
 member functions as virtual, in addition to a plethora of 
 non-virtual functions.

 I would like to be certain that the D compiler understands that 
 I would like it to treat those functions as virtual functions, 
 but unlike C++ where there is a `virtual` classifier for 
 functions, D does not appear to have such a facility.

 The C++ interop documentation suggests that both non- and 
 virtual functions are supported, but further suggests that it 
 only treats inherited functions as virtual with no method of 
 explicitly requesting virtual dispatch for that method.

 As far as I can tell, all specified member functions in a class 
 with C++ linkage are assumed to be non-virtual unless they are 
 overriden?
W.r.t. virtual member functions, D's syntax is more similar to Java than to C++, in that class member functions are virtual by default, unless marked as `final`. So to declare the following C++ class: class Base { virtual int fun(); int gun(); }; In D you have to do the following: extern (C++) class Base { int fun(); final int gun(); } Like all other attributes, you can group multiple members to which you want to apply the `final` attribute by either: class C { final { int gun(); int hun(); } } Or: class C { final: int gun(); int hun(); } Though be aware that unlike the protection attributes (public, private), there's no way to undo 'final:', so if you use it, you would have to move it with all the non-virtual methods to the bottom of the class definition.
Aug 13 2017
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 13.08.2017 09:18, Roman Hargrave wrote:
 I'm writing some bindings and have run in to a dilemma due to the lack 
 of explicit information on how the D compiler "decides" to use virtual 
 dispatch for a member function or not.
 
 Specifically, I have a C++ library that _explicitly_ marks some member 
 functions as virtual, in addition to a plethora of non-virtual functions.
 
 I would like to be certain that the D compiler understands that I would 
 like it to treat those functions as virtual functions, but unlike C++ 
 where there is a `virtual` classifier for functions, D does not appear 
 to have such a facility.
 ...
You can create one (this will look nicer with static foreach): struct virtual{} mixin template CheckVirtual(T){ import std.traits: isFinal, hasUDA; mixin({string r=""; foreach(m;__traits(allMembers,T)){ r~=`static assert(isFinal!(T.`~m~`)||hasUDA!(T.`~m~`,virtual),"'`~T.stringof~`.`~m~`' is neither final nor virtual");`; r~=`static assert(!isFinal!(T.`~m~`)||!hasUDA!(T.`~m~`,virtual),"'`~T.stringof~`.`~m~`' is both final and virtual");`; } return r;}()); } // example: extern(C++) class C{ final void foo(){} // ok virtual void bar(){} // ok void baz(){} // Error: static assert "'C.baz' is neither final not virtual" virtual final void qux(){} // Error: static assert "'C.qux' is both final and virtual" } mixin CheckVirtual!C;
 The C++ interop documentation suggests that both non- and virtual 
 functions are supported, but further suggests that it only treats 
 inherited functions as virtual with no method of explicitly requesting 
 virtual dispatch for that method.
 
 As far as I can tell, all specified member functions in a class with C++ 
 linkage are assumed to be non-virtual unless they are overriden?
All member functions are virtual by default. Only member functions explicitly marked as `final` are not virtual. The code above makes both explicit to help prevent mistakes.
Aug 13 2017