在boost.python中使用它时,不能在我的抽象类中使用纯虚函数

时间:2017-10-25 01:21:38

标签: python c++ boost polymorphism boost-python

我试图用我的C ++库扩展Python,我遇到了一些关于这个特例的问题:让我们说现在有一个名为Shape的抽象类我想允许Python从Shape继承并基本实现自己的Shape,但也能够在C ++代码中使用Shape的一些现有实现。让我展示一些代码:

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

很好,现在让我们说有一个名为Circle的C ++类。

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();
   }
};

然后以这种方式定义Shape:

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

好的,现在这是一个问题,因为Shape是一个抽象类,理所当然,它没有实现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})

现在,如果我在get_area类中Shape返回0.0作为默认行为,那么所有这些都将得到修复,但我不想以这样的方式编写我的API支持Python,我希望在函数不可用时有一个默认函数,并且只为Python返回0.0,因为抽象类的概念在Python中并没有以相同的方式存在。 #39;没关系,但我将Shape作为我的C ++ API的其余部分的抽象类。有没有办法做到这一点?

1 个答案:

答案 0 :(得分:2)

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

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