You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过pybind11在运行时获取对象的实际派生类型?

问题解决:在pybind11中获取C++对象的运行时实际类型

问题原因

你的代码存在两个关键问题导致无法获取实际派生类型:

  1. C++类非多态:Base类没有虚函数(包括虚析构),C++的RTTI(运行时类型信息)无法识别对象的实际派生类型,pybind11也无法正确关联到派生类的Python绑定。
  2. 错误的对象转换: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 21:23:15