1

Boost Python を使用して、C++ の一部のクラスに Python インターフェイスを提供しています。解決方法がわからないこの状況を見つけました:

このメンバー関数を持つクラスがあります:

virtual void visit(const ReportClass r) = 0;
virtual void visit(const unsigned int category) = 0;
virtual void visit(const char* type) = 0;
virtual void visit(const char* name, const unsigned int id, const char &value ) = 0;
virtual void visit(const char* name, const unsigned int id, const unsigned short &value ) = 0;
virtual void visit(const char* name, const unsigned int id, const unsigned int &value ) = 0;
virtual void visit(const char* name, const unsigned int id, const MaskedAddr &value ) = 0;
virtual void visit(const char* name, const unsigned int id, const unsigned long long &value ) = 0;

仮想関数とオーバーロードされた関数を処理する方法を見てきましたが、両方を組み合わせる方法がわかりません。

ちなみに、この例では、int を返す仮想関数 (たとえば) は次のように実装する必要があることがわかります。

int f()
{
    return this->get_override("f")();
}

私の場合、彼らは何も返さないので、次のように実装する必要があると思います:

void f()
{
     this->get_override("f")();
}

これは正しいです?

前もって感謝します

4

2 に答える 2

1

最初に簡単な質問をしてみましょう。returnタイプがvoidの場合でも、いつでも「return this-> get_override( "f")();」を実行できます。実際、そのようなラッパーコードでは、ラップされた関数が突然何かを返すと、コンパイルエラーが発生するため、さらに良い選択であることがわかります。

ここで難しい質問です。ここで仮想関数とオーバーロードされた関数を組み合わせる方法。テンプレートメソッドパターンを使用して、この問題を回避します。アイデアは、プライベート仮想関数を呼び出すパブリックの非仮想関数を提供することです。オプションで、オーバーライドする代わりに拡張を許可するために、仮想のものを保護することができます。さらに、非仮想のものでは、派生クラスがパラメーターを満たす必要がある前後の条件を検証または検証できます(例:assert(name);)。

于 2013-01-31T20:41:24.793 に答える
1

私があなたの質問を正しく理解していれば、純粋な仮想 (オーバーロードされた)メソッドを Pythonにバインドして、 python からオーバーロードできるようにする必要があります。あなたがすでに見つけたチュートリアルは、それを部分的に説明しています。あなたの特定のケースでは、C++ と Python はオーバーロードとうまく相互作用しません。C++ では許可されていますが、Python では禁止されています。fPython で同じ名前のメソッドを 2 つ持つことはできません。ユーザーが Python からオーバーライドを実装できるように、Python 呼び出しを分岐する必要があります。

より小さな例を書きますが、そこから抽象化できます。

C++ の配管から始めましょう。C++ バインディングは次のようになります。

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

    int f(int i) {
        return this->get_override("__f2__")()
    }

    int f(const char* s) {
        return this->get_override("__f3__")()
    }

    int f(const char* s, double d) {
        return this->get_override("__f4__")()
    }
};

//your module code will look like this
BOOST_PYTHON_MODULE(example) {
  using namespace boost::python;
  class_<BaseWrap, boost::noncopyable>("Base")
    .def("f", pure_virtual(((int)(Base::*)())&Base::f))
    .def("f", pure_virtual(((int)(Base::*)(int))&Base::f))
    .def("f", pure_virtual(((int)(Base::*)(const char*))&Base::f))
    .def("f", pure_virtual(((int)(Base::*)(const char*, double))&Base::f))
  ;
}

私たちは何をしましたか?コードの Python 側が を呼び出すとf(<parameters>)、適切なオーバーロードされたメソッドに解決されます。__f1__次に、このメソッドは Python の、などを呼び出します。このメソッド__f2__の肉は、Python から実際にコード化されています。

バインディングを完成させるには、Python で、、およびを継承しexample.Baseて実装する必要があります。__f1____f2____f3____f4__

class Base(example.Base):
  """Throw here the documentation of Base - don't bother about the C++ stuff"""

  def __init__(self,...):
    pass

  def __f1__(self):
    """Implementation of Base::f()"""
    pass

  def __f2__(self):
    """Implementation of Base::f(int)"""
    pass

  def __f3__(self):
    """Implementation of Base::f(const char*)"""
    pass

  def __f4__(self):
    """Implementation of Base::f(const char*, double)"""
    pass
于 2013-02-10T07:59:39.087 に答える