简体   繁体   English

在boost.python中使用抽象类时无法使用纯虚函数

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

I'm trying to extend Python with my C++ library and I'm running into a few issues with this particular case: Let's say there is an abstract class called Shape now I want to allow Python to inherit from Shape and basically implement its own Shape , but also be able to use some existing implementations of Shape in the C++ code. 我正在尝试使用我的C ++库扩展Python,并且在这种特殊情况下遇到了一些问题:假设有一个名为Shape的抽象类,现在我想允许Python从Shape继承并基本上实现其自己的Shape ,但还可以在C ++代码中使用Shape的某些现有实现。 Let me show some code: 让我显示一些代码:

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

Great, now let's say there is a C++ class called Circle . 太好了,现在我们说有一个名为Circle的C ++类。

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

Okay, let's write a wrapper for Shape (version 1): 好的,让我们为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();
   }
};

and then define Shape this way: 然后以这种方式定义Shape:

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

Okay, now this is a problem because Shape is an abstract class and rightfully so it doesn't implement get_area (it's pure virtual). 好的,现在这是一个问题,因为Shape是一个抽象类,并且理所当然地,它没有实现get_area (它是纯虚拟的)。 Alright, how about we scratch all of this and write it this way? 好吧,我们如何将所有这些抓取并以这种方式编写呢?

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

and then define Shape like this: 然后像这样定义Shape

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

Okay, so that works perfectly fine for the objects that Python overrides. 好的,这对于Python覆盖的对象来说效果很好。 However, if I create a Circle object within Python, it would give me the following error: 但是,如果我在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})

Now, all of this would be fixed IF I make get_area in the Shape class to return 0.0 as a default behavior but I don't want to write my API that way just to support Python, I'd like to have a default function for when the function isn't available and return 0.0 ONLY for Python because the notion of abstract classes doesn't exist in the same way in Python and that's fine but then I'll get to have Shape as an abstract class for the rest of my C++ API. 现在,如果我在Shape类中使get_area返回0.0作为默认行为,但是如果我不想仅以支持Python的方式编写API,则所有这些问题都将得到解决,我想为当函数不可用并仅对Python返回0.0时,因为抽象类的概念在Python中不存在,这很好,但是接下来我将把Shape作为其余部分的抽象类C ++ API。 Is there any way to do this? 有什么办法吗?

Thanks to @llonesmiz, I realized the issue was that the wrappers function was passed to the pure virtual's function. 感谢@llonesmiz,我意识到问题在于将包装器函数传递给了纯虚函数。 Defining ShapeWrapper this way would resolve the issue: ShapeWrapper这种方式定义ShapeWrapper可以解决此问题:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM