Inheritance

これまでの例題はクラスを多様な形態ではないものとしてあつかってきた。 こういうケースは少ない。 多くの場合、多様なクラスや継承により階層化されたクラスをラッピングするだろう。 しばしば、抽象基底クラスから派生するクラスのために Boost.Python ラッパーを書く必要がある。

このつまらない継承クラスで考えよう。

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

そしてBaseDerivedオブジェクトの実体を操作する C++ 関数セット。

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

基底クラスBaseのラッピングはこのように表現する。

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

これでやっとDerivedとその基底クラスBaseの継承関係を Boost.Python に情報としてあたえることができる。

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

こうすることで幾つかのことが自由になる。

  1. C++ メンバ関数をラップした Python Base 関数のあらゆる継承を自動的に得る。
  2. Base が多態的な場合、 Pythonに渡すDerivedオブジェクト、 またBaseへのポインタや参照は、 Derivedが期待するポインタや参照に設定される。

C++ の自由な関数 bdfactory を開示する。

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

自由な関数factoryDerivedクラスの新しいインスタンスを生成していることに注意しなさい。 このような場合、return_value_policy<manage_new_object>を使う。 これはBaseへのポインタを採用するように、 また新しいオブジェクト Python Baseが破壊されるまで、 その中に実体を保持するよう Python に指示する。

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