boost.python -- 继承

以官网文为本,尽量翻译下,方便以后看。我使用的boost 版本为1.5.1 。原谅网址:http://www.boost.org/doc/libs/1_51_0/libs/python/doc/tutorial/doc/html/python/exposing.html#python.inheritance

Inheritance

继承

In the previous examples, we dealt with classes that are not polymorphic. This is not often the case. Much of the time, we will be wrapping polymorphic classes and class hierarchies related by inheritance. We will often have to write Boost.Python wrappers for classes that are derived from abstract base classes.

在前面的例子中,我们处理的类并不具备多态性,在实际情况中并不多。大多时候,我们会包装多态类和类的继承关系。我们也经常用boost.python包装从绝虚基类继承而来的类。


Consider this trivial inheritance structure:

看下面这个简单的继承结构:

struct Base { virtual ~Base(); };
struct Derived : Base {};

And a set of C++ functions operating on Base and Derived object instances:

并且一些c++函数操作这些Base类和Derived类的对象:

void b(Base*);
void d(Derived*);
Base* factory() { return new Derived; }

We've seen how we can wrap the base class Base:

下面演示怎么封装基类:

class_<Base>("Base")
    /*...*/
    ;

Now we can inform Boost.Python of the inheritance relationship between Derived and its base class Base. Thus:

现在我们可以告诉boost.python  Derived类和它的基类Base之间的继承关系。因此:

class_<Derived, bases<Base> >("Derived")
    /*...*/
    ;

Doing so, we get some things for free:

  1. Derived automatically inherits all of Base's Python methods (wrapped C++ member functions)
  2. If Base is polymorphic, Derived objects which have been passed to Python via a pointer or reference to Base can be passed where a pointer or reference to Derived is expected.
做这些之后,我们获得了一些额外的效果:
  1.  Derived 类自动继承了Base 类的python 方法(包装的c++ 成员函数)
  2.  如果Base 是多态的,通过指针或引用被传给Python 的 Derived 对象也可以用指针或引用传递到需要Derived对象做参数的地方。

Now, we will expose the C++ free functions b and d and factory:

现在我们会暴露c++ 函数 b , d 和factory:

def("b", b);
def("d", d);
def("factory", factory);

Note that free function factory is being used to generate new instances of class Derived. In such cases, we usereturn_value_policy<manage_new_object> to instruct Python to adopt the pointer to Base and hold the instance in a new Python Baseobject until the the Python object is destroyed. We will see more of Boost.Python call policies later.


需要说明的是,自由函数 factory 用来制造Derived 类的对象。在这些例子中,我们使用 return_value_policy<manage_new_object> 告诉 Python 接收Base的指针,在Python的Base对象(即包装好的Python的Base类,和先前的C++的Base类不是一个类)中保存这个实例,直到这个Python 对被销毁。在Boost.Python 的 call policies 可以看到更多相关信息。

// Tell Python to take ownership of factory's result
def("factory", factory,
    return_value_policy<manage_new_object>());

Class Virtual Functions

类虚函数

In this section, we will learn how to make functions behave polymorphically through virtual functions. Continuing our example, let us add a virtual function to our Base class:

在这一部分中,我们将学习通过虚函数怎样实现多态性。继承我们的例子,现在给Base类添加一个虚函数:

struct Base
{
    virtual ~Base() {}
    virtual int f() = 0;
};

One of the goals of Boost.Python is to be minimally intrusive on an existing C++ design. In principle, it should be possible to expose the interface for a 3rd party library without changing it. It is not ideal to add anything to our class Base. Yet, when you have a virtual function that's going to be overridden in Python and called polymorphically from C++, we'll need to add some scaffoldings to make things work properly. What we'll do is write a class wrapper that derives from Base that will unintrusively hook into the virtual functions so that a Python override may be called:

Boost.Python的目标之一是最少化地减少对现在有的c++设计的更改。原则上讲,应该做到在给第三方库提供接口里不更改原有设计。对Base类添加任何代码都是不理想的。还有,当有一个在Python中会被重写,并且从C++使用多态的虚函数时,我们必须添加一些辅助代码以保证程序的正常运行。我们需要做的就是从Base中新继承一个类(PS:通常应该是最后一个类,比如A为基类,B继承A,如果再继承A来封装,势必不能转为类B的对象),并封装它,这样就在不修改的同时给虚函数添加了一个钩,以使在Python中重写函数后也可调用:

struct BaseWrap : Base, wrapper<Base>
{
    int f()
    {
        return this->get_override("f")();
    }
};

Notice too that in addition to inheriting from Base, we also multiply- inherited wrapper<Base> (See Wrapper). The wrapper template makes the job of wrapping classes that are meant to overridden in Python, easier.


注意在从Base类继承的同时,我们也多重继承了 wrapper<Base>  (详见  Wrapper ). 这个wrapper template 使封装类,换句话说,在Python中重写虚函数变得更简单。

PS:例子中使用的是struct , 而不是class .直接改成class,会导致," 存在 BaseWrap 到 wrapper<Base> 的转换,但无法访问 ", 所以使用class 应该这样写:
class BaseWrap : public Base, public wrapper<Base> {...};


BaseWrap's overridden virtual member function f in effect calls the corresponding method of the Python object through get_override.

BaseWrap 重写的虚函数 f 在运行时通过get_override(...) 调用相应的Python对象的方法。

Finally, exposing Base:

最后,暴露 Base :

class_<BaseWrap, boost::noncopyable>("Base")
    .def("f", pure_virtual(&Base::f))
    ;

pure_virtual signals Boost.Python that the function f is a pure virtual function.

pure_virtual符号 告诉 Boost.Python 函数 f 是纯虚函数。

[Note]Note
注意

member function and methods

成员函数方法

Python, like many object oriented languages uses the term methods. Methods correspond roughly to C++'s member functions

Python, 像许多面对对象语言使用方法,在c++中方法被称作成员函数。



Virtual Functions with Default Implementations

有默认实现的虚函数

We've seen in the previous section how classes with pure virtual functions are wrapped using Boost.Python's class wrapper facilities. If we wish to wrap non-pure-virtual functions instead, the mechanism is a bit different.

在先前的章节中,我们学习了如何使用Boost.Python 类 wrapper 工具封装纯虚函数。如果我们想封装非纯虚函数,这个工作机制有一点不同。

Recall that in the previous section, we wrapped a class with a pure virtual function that we then implemented in C++, or Python classes derived from it. Our base class:

在先前的章节中,我们封装了有纯虚函数的c++类,或者继承于它的Python类。我们的基类:

struct Base
{
    virtual int f() = 0;
};

had a pure virtual function f. If, however, its member function f was not declared as pure virtual:

有一个纯虚函数f。然而,如果它的成员函数f不是声明为纯虚函数:

struct Base
{
    virtual ~Base() {}
    virtual int f() { return 0; }
};

We wrap it this way:

我们要这样封装它:

struct BaseWrap : Base, wrapper<Base>
{
    int f()
    {
        if (override f = this->get_override("f"))
            return f(); // *note*
        return Base::f();
    }

    int default_f() { return this->Base::f(); }
};

Notice how we implemented BaseWrap::f. Now, we have to check if there is an override for f. If none, then we call Base::f().

注意我们怎么实现 BaseWrap::f . 现在我们必须检查是否存在函数f的重写。如果没有,我们调用 Base::f().

Finally, exposing:

最后,这样提供接口:

class_<BaseWrap, boost::noncopyable>("Base")
    .def("f", &Base::f, &BaseWrap::default_f)
    ;

Take note that we expose both &Base::f and &BaseWrap::default_f. Boost.Python needs to keep track of 1) the dispatch function f and 2) the forwarding function to its default implementation default_f. There's a special def function for this purpose.

注意我们同时暴露了&Base::f and &BaseWrap::default_f .  Boost.Python 需要追踪 1)调度函数f 2)其默认实现的函数default_f 。为了达到这个目的,这里有一个特殊的def函数。

In Python, the results would be as expected:

在Python中,结果应该是这样的:

>>> base = Base()
>>> class Derived(Base):
...     def f(self):
...         return 42
...
>>> derived = Derived()

Calling base.f():

>>> base.f()
0

Calling derived.f():

>>> derived.f()
42


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值