不能以这种方式将抽象C
类公开给Boost.Python。Boost.Python教程提供了有关如何公开纯虚函数的示例。简而言之,当使用修饰装饰方法时boost::python::pure_virtual
,需要创建包装器类型,以允许C
对虚拟函数进行多态解析,并且虚拟函数实现将在Python对象的层次结构中委派多态解析函数。
struct baseWrap : base, boost::python::wrapper<base>{ int foo() { return this->get_override("foo")(); }};...boost::python::class_<baseWrap>("base", ...) .def("foo", boost::python::pure_virtual(&base::foo)) ;有关详细信息,当通过公开类型时
boost::python::class_,
HeldType默认为公开的类型,并且
HeldType在Python对象中构造。该
class_文档指出:
模板参数:
T:正在包装的课程 HeldType:指定包装T实例的Python对象中实际嵌入的类型[…]。默认为T。
因此,该操作
boost::python::class_<base>将失败,因为
T = baseand
HeldType =base和Boost.Python将尝试将对象实例
HeldType化为表示实例的Python对象
base。此实例化将失败,就像
base抽象类一样。
这是显示
baseWrap类使用的完整示例。
#include <boost/python.hpp>struct base{ virtual int foo() = 0; virtual ~base() {}};struct Derived : public base{ virtual int foo() { return 42; }};base* get_base(){ return new Derived;}namespace python = boost::python;/// @brief Wrapper that will provide a non-abstract type for base.struct baseWrap : base, python::wrapper<base>{ baseWrap() {} baseWrap(const base& rhs) : base(rhs) {} int foo() { return this->get_override("foo")(); }};BOOST_PYTHON_MODULE(example){ python::class_<baseWrap>("base") .def("foo", python::pure_virtual(&base::foo)); ; python::def("get_base", &get_base, python::return_value_policy<python::manage_new_object>());}及其用法:
>>> import example>>> class Spam(example.base):... pass... >>> Spam().foo()Traceback (most recent call last): File "<stdin>", line 1, in <module>RuntimeError: Pure virtual function called>>> class Egg(example.base):... def foo(self):... return 100... >>> e = Egg()>>> e.foo()100>>> d = example.get_base()>>> d.foo()42
可以通过不使用默认初始化器(
boost::python::no_init)和不可复制(
boost::noncopyable)进行公开来在Boost.Python中公开一个抽象类。缺少初始化器会阻止从其派生Python类型,从而有效地防止覆盖。另外,
base::foo()在C
++中由实现的实现细节
Derived是无关紧要的。如果Python根本不了解某个
foo()方法,请省略通过公开它
def()。
#include <boost/python.hpp>struct base{ virtual int foo() = 0; virtual ~base() {}};struct Derived : public base{ virtual int foo() { return 42; }};struct OtherDerived : public base{ virtual int foo() { return 24; }};base* get_base(){ return new Derived;}base* get_other_base(){ return new OtherDerived;}BOOST_PYTHON_MODULE(example){ namespace python = boost::python; python::class_<base, boost::noncopyable>("base", python::no_init) ; python::class_<Derived, python::bases<base> >("Derived", python::no_init) .def("foo", &base::foo) ; python::class_<OtherDerived, python::bases<base> >( "OtherDerived", python::no_init) ; python::def("get_base", &get_base, python::return_value_policy<python::manage_new_object>()); python::def("get_other_base", &get_other_base, python::return_value_policy<python::manage_new_object>());}互动用法:
>>> import example>>> b = example.get_base()>>> b.foo()42>>> b = example.get_other_base()>>> b.foo()Traceback (most recent call last): File "<stdin>", line 1, in <module>AttributeError: 'OtherDerived' object has no attribute 'foo'



