【问题标题】: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;
}