具有pybind的多态类 我想用pyBIN将多态C++类层次结构封装到Python。

具有pybind的多态类 我想用pyBIN将多态C++类层次结构封装到Python。,python,c++,pybind11,Python,C++,Pybind11,我的意图是Python类继承了Python代码中的包C++类,并覆盖了一些函数。在下面的例子中,有一个Python类猫,它继承了C++类的动物和oviWrand函数GO()。这正在工作,print(test.call\u go(c)按预期打印“喵!喵!喵!” Python类贝洛继承C++类狗,应该覆盖函数BARK()和GO()。但是它不起作用。BARK()和GO()是否被类贝洛重写。< /P> print(test.call_go(b))print“呜!呜!呜!”。我希望是“grrrr!grr

我的意图是Python类继承了Python代码中的包C++类,并覆盖了一些函数。在下面的例子中,有一个Python类猫,它继承了C++类的动物和oviWrand函数GO()。这正在工作,

print(test.call\u go(c)
按预期打印“喵!喵!喵!”

Python类贝洛继承C++类狗,应该覆盖函数BARK()和GO()。但是它不起作用。BARK()和GO()是否被类贝洛重写。< /P>

print(test.call_go(b))
print“呜!呜!呜!”。我希望是“grrrr!grrrr!grrrr!”

print(test.call_bark(b))
prints“woof!”。我希望是“grrrr!”

pybind Inhination似乎只适用于一个多态级别。我天真的期望是,它与CPP类似或类似。我只能从直接继承的类重写函数

我希望你能给我一个提示让它工作或者告诉我为什么它不能工作。提前谢谢你

我尝试了以下修改:

  • 将PyDog用作蹦床而不是动物--
    py::class_m(“狗”)
    • 在python代码中调用print(test.call_go(d))会导致一个错误,因为d不再是Animal类型。我不知道为什么,因为PyDog继承自Animal。函数bark()按预期过度编写
  • 若python类Bello继承自test.Animal而非test.Dog,那个么函数go将按预期被覆盖
这是我的cpp代码:


你有没有发现答案?我很好奇你有没有发现答案?我也很好奇
class Animal {
public:
    virtual std::string go(int n_times) = 0;
    virtual std::string name() { return "unknown"; }
};
class Dog : public Animal {
public:
    std::string go(int n_times) override {
        std::string result;
        for (int i=0; i<n_times; ++i)
            result += bark() + " ";
        return result;
    }
    virtual std::string name() { return "Dog"; }
    virtual std::string bark() { return "woof!"; }
};

class PyAnimal : public Animal {
public:
    using Animal::Animal; // Inherit constructors
    std::string go(int n_times) override { PYBIND11_OVERLOAD_PURE(std::string, Animal, go, n_times); }
    std::string name() override { PYBIND11_OVERLOAD(std::string, Animal, name, ); }
};
class PyDog : public Dog {
public:
    using Dog::Dog; // Inherit constructors
    std::string go(int n_times) override { PYBIND11_OVERLOAD(std::string, Dog, go, n_times); }
    std::string name() override { PYBIND11_OVERLOAD(std::string, Dog, name, ); }
    std::string bark() override { PYBIND11_OVERLOAD(std::string, Dog, bark, ); }
};

std::string call_go(Animal *animal) {
    return animal->go(3);
}

std::string call_bark(Dog *dog) {
    return dog->bark();
}



PYBIND11_MODULE(_MyTest, m)
{
    py::class_<Animal, PyAnimal /* <--- trampoline*/>(m, "Animal")
        .def(py::init<>())
        .def("go", &Animal::go);

    py::class_<Dog, Animal>(m, "Dog")
        .def(py::init<>())
        .def("go", &Dog::go)
        .def("bark", &Dog::bark);

    m.def("call_go", &call_go);
    m.def("call_bark", &call_bark);
}
#!/usr/bin/env python3

import sys
from ATOM import _MyTest as test


def main(argv=None):
    print("check Dog")
    d = test.Dog()
    print(test.call_go(d))
    print(test.call_bark(d))

    class Cat(test.Animal):
        def go(self, n_times):
            return "meow! " * n_times

    print("check Cat")
    c = Cat()
    print(test.call_go(c))

    print("check Bello")
    class Bello(test.Dog):
        def go(self, n_times):
            return "grrrr! " * n_times

        def bark(self):
            return "grrrr! "

    b = Bello()
    print(test.call_go(b))
    print(test.call_bark(b))
    print(b.go(3))
    print(b.bark())

if __name__ == "__main__":
    sys.exit(main())