【问题标题】:PyBind11 function argument is a base class pointer - if I pass a derived class it tells me it's an unsupported typePyBind11 函数参数是一个基类指针——如果我传递一个派生类,它会告诉我它是一个不受支持的类型
【发布时间】:2022-12-20 06:07:32
【问题描述】:

使用 pybind11 包装时,采用基类的函数定义不会将派生类识别为有效参数。在 pybind11 我有定义

class BaseClass
{
public:
    BaseClass() {}
    virtual void someFunc() { cout << "base\n"; }
};

class DerivedClass : public BaseClass
{
public:
    DerivedClass() {}
    void someFunc() override { cout << "derived\n"; }
};

class OtherClass
{
public:
    OtherClass() {}
    void someCall(BaseClass *other)
    {
        other->someFunc();
    }
};

蟒蛇看起来像这样

dc = DerivedClass()
oc = OtherClass()
oc.someCall(dc)

我得到错误

E       TypeError: someCall(): incompatible function arguments. The following argument types are supported:
E           1. (self: solver.OtherClass, arg0: solver.BaseClass) -> None
E
E       Invoked with: <solver.OtherClass object at 0x000001DB1C992530>, <pygsolver.DerivedClass object at 0x000001DB1C992170>

我如何使它工作以便 DerivedClass 与这个函数调用一起工作?谢谢你的帮助!

【问题讨论】:

    标签: python function inheritance pybind11


    【解决方案1】:

    您需要在 C++ 中使用多态性。在 someCall 函数中,可以添加一个 dynamic_cast 将 BaseClass 指针转换为指向派生类的指针。这将允许您调用派生类的 someFunc 函数。

    以下是如何执行此操作的示例:

    class OtherClass
    {
    public:
        OtherClass() {}
        void someCall(BaseClass *other)
        {
            DerivedClass *derived = dynamic_cast<DerivedClass *>(other);
            if (derived)
            {
                // Call the derived class's implementation of someFunc
                derived->someFunc();
            }
            else
            {
                // Call the base class's implementation of someFunc
                other->someFunc();
            }
        }
    };
    

    现在,当您使用 DerivedClass 的实例调用 someCall 时,它将调用派生类的 someFunc 实现,而当您使用 BaseClass 的实例或任何其他不是从 BaseClass 派生的类调用它时,它将调用基类的实现一些功能。

    请注意,为了使其工作,BaseClass 类需要有一个虚拟析构函数。这是因为 dynamic_cast 操作涉及在运行时检查对象的类型,这要求析构函数是虚拟的,以便在删除对象时调用正确的析构函数。

    以下是包含这些更改的完整代码:

    #include <iostream>
    #include <memory>
    
    class BaseClass
    {
    public:
        BaseClass() {}
        virtual ~BaseClass() {} // Added a virtual destructor
        virtual void someFunc() { std::cout << "base
    "; }
    };
    
    class DerivedClass : public BaseClass
    {
    public:
        DerivedClass() {}
        void someFunc() override { std::cout << "derived
    "; }
    };
    
    class OtherClass
    {
    public:
        OtherClass() {}
        void someCall(BaseClass *other)
        {
            DerivedClass *derived = dynamic_cast<DerivedClass *>(other);
            if (derived)
            {
                // Call the derived class's implementation of someFunc
                derived->someFunc();
            }
            else
            {
                // Call the base class's implementation of someFunc
                other->someFunc();
            }
        }
    };
    
    int main()
    {
        std::unique_ptr<BaseClass> bc(new BaseClass());
        std::unique_ptr<DerivedClass> dc(new DerivedClass());
        OtherClass oc;
    
        oc.someCall(bc.get()); // This should print "base"
        oc.someCall(dc.get()); // This should print "derived"
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-23
      • 1970-01-01
      • 2021-11-19
      • 1970-01-01
      • 1970-01-01
      • 2019-07-22
      • 2013-08-15
      • 1970-01-01
      相关资源
      最近更新 更多