【问题标题】:Several virtual member functions with different signature几个不同签名的虚成员函数
【发布时间】:2013-01-15 11:47:29
【问题描述】:

我正在使用 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;

我对如何实现 python-boost 部分有点迷茫,我已经看到如何处理虚函数和重载函数,但我不知道如何将两者结合起来。

顺便说一句,我在示例中看到返回 int 的虚函数(例如)应该以这种方式实现:

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

在我的情况下,它们没有返回任何东西,我想我应该以这种方式实现它们:

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

这对吗?

提前致谢

【问题讨论】:

  • 过度收费功能?那是什么?

标签: c++ python boost boost-python


【解决方案1】:

如果我正确理解您的问题,您希望将 纯虚拟(重载) 方法绑定到 Python,以便它们可以从 python 重载。您拥有already found 的教程部分解释了这一点。在您的特定情况下,C++ 和 Python 不能很好地与重载相互作用。虽然 C++ 允许,但 Python 禁止。在 Python 中不能有两个名称为 f 的方法。我们要做的是分散 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(&lt;parameters&gt;) 时,我们将解析到正确的重载方法。然后,此方法将从 Python 调用 Python 的 __f1____f2__ 等,其中方法的实质是真正编码的。

要完成绑定,在 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

【讨论】:

    【解决方案2】:

    让我们先回答一个简单的问题:即使返回类型为 void,您也始终可以“返回 this->get_override("f")();”。实际上,在这样的包装代码中,我发现更好的选择,因为如果突然包装的函数返回一些东西,你会得到一个编译错误!

    现在是一个难题:如何在这里混合使用虚函数和重载函数。我会使用模板方法模式来规避这个问题。这个想法是简单地提供一个公共的、非虚拟的函数来调用一个私有的虚拟函数。或者,您可以使虚拟的受保护,以允许扩展而不是覆盖。此外,在非虚拟类中,您可以验证派生类必须满足或验证参数的前置/后置条件(例如 assert(name);)。

    【讨论】:

      猜你喜欢
      • 2022-01-23
      • 2011-06-20
      • 1970-01-01
      • 2018-01-22
      • 2013-03-22
      • 1970-01-01
      • 2021-10-16
      • 1970-01-01
      • 2011-06-17
      相关资源
      最近更新 更多