pybind11/example/example-virtual-functions.py
Jason Rhinelander 0ca96e2915 Added advanced doc section on virtual methods + inheritance
As discussed in #320.

The adds a documentation block that mentions that the trampoline classes
must provide overrides for both the classes' own virtual methods *and*
any inherited virtual methods.  It also provides a templated solution to
avoiding method duplication.

The example includes a third method (only mentioned in the "see also"
section of the documentation addition), using multiple inheritance.
While this approach works, and avoids code generation in deep
hierarchies, it is intrusive by requiring that the wrapped classes use
virtual inheritance, which itself is more instrusive if any of the
virtual base classes need anything other than default constructors.  As
per the discussion in #320, it is kept as an example, but not suggested
in the documentation.
2016-08-05 18:02:37 -04:00

106 lines
2.8 KiB
Python

#!/usr/bin/env python
from __future__ import print_function
import sys
sys.path.append('.')
from example import ExampleVirt, runExampleVirt, runExampleVirtVirtual, runExampleVirtBool
from example import A_Repeat, B_Repeat, C_Repeat, D_Repeat, A_MI, B_MI, C_MI, D_MI, A_Tpl, B_Tpl, C_Tpl, D_Tpl
class ExtendedExampleVirt(ExampleVirt):
def __init__(self, state):
super(ExtendedExampleVirt, self).__init__(state + 1)
self.data = "Hello world"
def run(self, value):
print('ExtendedExampleVirt::run(%i), calling parent..' % value)
return super(ExtendedExampleVirt, self).run(value + 1)
def run_bool(self):
print('ExtendedExampleVirt::run_bool()')
return False
def pure_virtual(self):
print('ExtendedExampleVirt::pure_virtual(): %s' % self.data)
ex12 = ExampleVirt(10)
print(runExampleVirt(ex12, 20))
try:
runExampleVirtVirtual(ex12)
except Exception as e:
print("Caught expected exception: " + str(e))
ex12p = ExtendedExampleVirt(10)
print(runExampleVirt(ex12p, 20))
print(runExampleVirtBool(ex12p))
runExampleVirtVirtual(ex12p)
sys.stdout.flush()
class VI_AR(A_Repeat):
def unlucky_number(self):
return 99
class VI_AMI(A_MI):
def unlucky_number(self):
return 990
def say_something(self, times):
return A_MI.say_something(self, 2*times)
class VI_AT(A_Tpl):
def unlucky_number(self):
return 999
class VI_CR(C_Repeat):
def lucky_number(self):
return C_Repeat.lucky_number(self) + 1.25
class VI_CMI(C_MI):
def lucky_number(self):
return 1.75
class VI_CT(C_Tpl):
pass
class VI_CCR(VI_CR):
def lucky_number(self):
return VI_CR.lucky_number(self) * 10
class VI_CCMI(VI_CMI):
def lucky_number(self):
return VI_CMI.lucky_number(self) * 100
class VI_CCT(VI_CT):
def lucky_number(self):
return VI_CT.lucky_number(self) * 1000
class VI_DR(D_Repeat):
def unlucky_number(self):
return 123
def lucky_number(self):
return 42.0
class VI_DMI(D_MI):
def unlucky_number(self):
return 1230
def lucky_number(self):
return -9.5
class VI_DT(D_Tpl):
def say_something(self, times):
print("VI_DT says:" + (' quack' * times))
def unlucky_number(self):
return 1234
def lucky_number(self):
return -4.25
classes = [
# A_Repeat, A_MI, A_Tpl, # abstract (they have a pure virtual unlucky_number)
VI_AR, VI_AMI, VI_AT,
B_Repeat, B_MI, B_Tpl,
C_Repeat, C_MI, C_Tpl,
VI_CR, VI_CMI, VI_CT, VI_CCR, VI_CCMI, VI_CCT,
D_Repeat, D_MI, D_Tpl, VI_DR, VI_DMI, VI_DT
]
for cl in classes:
print("\n%s:" % cl.__name__)
obj = cl()
obj.say_something(3)
print("Unlucky = %d" % obj.unlucky_number())
if hasattr(obj, "lucky_number"):
print("Lucky = %.2f" % obj.lucky_number())