在 boost.python 中使用时无法在我的摘要 class 中使用纯虚函数

Cannot use pure virtual functions in my abstract class when using it in boost.python

我正在尝试用我的 C++ 库扩展 Python,我 运行 遇到了这个特殊情况的一些问题:假设有一个抽象 class 叫做Shape 现在我想允许 Python 继承自 Shape 并基本上实现它自己的 Shape,但也能够在 C++ 代码中使用 Shape 的一些现有实现。让我展示一些代码:

class Shape {
public:
    virtual inline double get_area() const = 0;
};

太好了,现在假设有一个名为 Circle.

的 C++ class
class Circle : public Shape {
public:
    Circle() = default;
    inline double get_area() const override { return 0.5; }
}

好的,让我们为 Shape(版本 1)写一个包装器:

struct ShapeWrap : public Shape, public wrapper<Shape>{
   inline double get_area() const override {
      if (auto py_func = this->get_override("get")) return py_func();
      return Shape::get_area();
   }
   inline double default_get_area() const {
      return this->Shape::get_area();
   }
};

然后这样定义形状:

class_<ShapeWrap, boost::noncopyable>("Shape")
        .def("get_area", &Shape::get_area, &ShapeWrap::default_get_area));

好吧,现在这是一个问题,因为 Shape 是一个抽象 class 并且理所当然地它没有实现 get_area(它是纯虚拟的)。好吧,我们把这些都划掉然后这样写怎么样?

struct ShapeWrap : public Shape, public wrapper<Shape>{
   inline double get_area() const override {
      if (auto py_func = this->get_override("get")) return py_func();
      return 0.0;
   }
};

然后像这样定义 Shape

class_<ShapeWrap, boost::noncopyable>("Shape")
        .def("get_area", pure_virtual(&ShapeWrap::get_area));

好的,这对于 Python 覆盖的对象来说工作得很好。但是,如果我在 Python 中创建一个 Circle 对象,它会给我以下错误:

Boost.Python.ArgumentError: Python argument types in
    Shape.get_area(Circle)
did not match C++ signature:
    get_area(ShapeWrap {lvalue})
    get_area(ShapeWrap {lvalue})

现在,如果我将 Shape class 中的 get_area 设置为 return 0.0 作为默认行为,所有这些都将得到修复,但我不想以这种方式编写我的 API 只是为了支持 Python,我希望在该功能不可用时有一个默认功能,而 return 0.0 仅适用于 Python因为抽象 classes 的概念在 Python 中并不以相同的方式存在,这很好,但是我会得到 Shape 作为抽象 class我的 C++ API 的其余部分。有什么办法吗?

感谢@llonesmiz,我意识到问题是包装函数被传递给了纯虚拟函数。以这种方式定义 ShapeWrapper 可以解决问题:

class_<ShapeWrap, boost::noncopyable>("Shape")
    .def("get_area", pure_virtual(&Shape::get_area));