如何通过pybind11在运行时获取对象的实际派生类型?
问题解决:在pybind11中获取C++对象的运行时实际类型
问题原因
你的代码存在两个关键问题导致无法获取实际派生类型:
- C++类非多态:
Base类没有虚函数(包括虚析构),C++的RTTI(运行时类型信息)无法识别对象的实际派生类型,pybind11也无法正确关联到派生类的Python绑定。 - 错误的对象转换:
py::cast(self)会创建一个新的Base类型Python对象,而非获取当前实例对应的、关联派生类的Python对象,因此得到的类型始终是Base。
解决方案
步骤1:将Base类改为多态类型
给Base类添加虚析构函数(或任意虚函数),使其成为多态类,这样C++ RTTI和pybind11都能正确追踪实际类型:
class Base { public: // 虚析构函数,使Base成为多态类型 virtual ~Base() = default; }; class Derived : public Base {};
步骤2:修改__repr__的实现
在绑定代码中,通过指针转换获取关联的Python对象,进而得到实际运行时类型:
PYBIND11_MODULE(mwe, m) { py::class_<Base>(m, "Base") .def("__repr__", [](const Base& self) { // 获取当前C++对象对应的Python实例 py::object py_self = py::cast(&self, py::return_value_policy::reference_internal); // 返回实际类型的名称 return py_self.get_type().attr("__name__").cast<std::string>(); }); py::class_<Derived, Base>(m, "Derived") .def(py::init<>()); }
代码验证
运行Python测试代码:
from mwe import Base, Derived print(Derived()) # 输出:Derived print(Base()) # 输出:Base
补充说明
py::return_value_policy::reference_internal确保我们获取的是已存在的Python对象引用,而非创建新对象,避免类型信息丢失。- 也可以用
py::type::of(py_self)替代py_self.get_type(),两者效果一致。
内容的提问来源于stack exchange,提问作者matheburg
相关产品推荐
相关产品推荐

