python - 虚拟继承 C++ 和 boost python

标签 python c++ boost-python virtual-inheritance

在我正在开发的游戏中,我有两个 C++ 类(ICollidable 和 Sprite),它们实际上都继承了另一个名为 Object 的 C++ 类,因为它具有位置和大小属性。我使用 boost python 将这三个类暴露给 python。 python 中的 Player 类构造函数如下所示:

class Player(Game.ICollidable, Game.Sprite, Game.IKeyboardListener, Game.IEntity):
    def __init__(self):
        Game.IKeyboardListener.__init__(self)
        Game.IEntity.__init__(self)    
        Game.ICollidable.__init__(self)
        Game.Sprite.__init__(self)

问题是,当 Sprite init 出现在 ICollidable 的 init 之前时,Sprite 位置无法正常工作,我无法在屏幕上重新定位 sprite。我认为发生的事情是 Sprite 和 ICollidable 的位置有单独的实例,这是我在创建 ICollidable 类之前认为会发生的情况。

我已经尝试了各种方法来尝试解决这个问题,并在互联网上搜索以找到解决此类问题的方法,但我一无所获。任何建议、解决方案或提示将不胜感激。

编辑:

这些是我的 C++ 类的 python 绑定(bind):

class_<Object>("GameObject")
    .def_readwrite("Pos", &Object::pos)
    .def_readwrite("Size",&Object::size)
;
class_<Sprite, bases<Object>>("Sprite", init<>())
    // Sprite(TexID, Pos)
    .def(init<GLuint, glm::vec2>())
    // ----------------------------
    .def_readwrite("TexId", &Sprite::texid)
;
class_<ICollidableWrap, bases<Object>,boost::noncopyable>("ICollidable", init<>())
    //.def("Pos", &ICollidable::Object::pos)
    .def("Test", pure_virtual(&ICollidable::Test))
    .def("OnCollision",pure_virtual(&ICollidable::OnCollision))
;

最佳答案

虽然这两种语言都提供了 the diamond problem 的解决方案,他们使用不同的方法。 C++ 消除了虚拟继承的歧义,导致共享单个子对象。另一方面,Python 通过单调父类(super class)线性化查找消除了歧义。由于 Python 继承不会导致 C++ 类型共享单个子对象,因此当 Python 类继承自共享公共(public)虚拟基的两个公开的 C++ 类时,Boost.Python 将需要模拟 C++ 虚拟继承。不幸的是,据我所知,Boost.Python 不支持这种情况,因为提供给 boost::python::bases<...> 的类型。不检查虚拟继承。

虽然不可扩展并且可能表明可能值得研究基于组合的解决方案,但一个简单的继承解决方案是公开一个 CollidableSpriteICollidableWrap 继承的 C++ 类和 Sprite ,然后让 Python 类继承自 CollidableSprite .


这是一个基本示例,其中类 C继承自 BA该虚拟继承自 V :

#include <boost/python.hpp>

/// @brief Mock up forming the following multiple inheritance
///        structure:
///
///            .-->[ V ]<--.
///            |           |
///          [ A ]       [ B ]
///            |           |
///            '---[ C ] --'
struct V
{
  V() : x(0) {}
  virtual ~V() {}
  unsigned int x;
};

struct A : virtual public V {};
struct B : virtual public V {};
struct C : public A, public B {};

/// @brief Functions that force an object's hierarchy chain to be
///        split, disambiguating access to V.x.
void print_a(A& a) { std::cout << a.x << std::endl; }
void print_b(B& b) { std::cout << b.x << std::endl; }

BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;
  // Expose hierarchy.
  python::class_<V>("V", python::no_init)
    .def_readwrite("x", &V::x)
    ;
  python::class_<A, python::bases<V> >("A");
  python::class_<B, python::bases<V> >("B");
  python::class_<C, python::bases<A, B> >("C");

  // Expose helper functions.
  python::def("print_a", &print_a);
  python::def("print_b", &print_b);
}

交互使用:

>>> import example
>>> class PyC(example.A, example.B):
...     def __init__(self):
...         example.A.__init__(self)
...         example.B.__init__(self)
... 
>>> c = PyC()
>>> example.print_a(c)
0
>>> example.print_b(c)
0
>>> c.x = 42
>>> example.print_a(c)
0
>>> example.print_b(c)
42
>>> class PyC(example.C):
...     pass
... 
>>> c = PyC()
>>> example.print_a(c)
0
>>> example.print_b(c)
0
>>> c.x = 42
>>> example.print_a(c)
42
>>> example.print_b(c)
42

关于python - 虚拟继承 C++ 和 boost python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21221628/

相关文章:

Python NetworkX — 根据值列表自动设置节点颜色

python - 过滤器对象没有属性 pop

python - Python中的正则表达式从右到左解析

c++解析文件并读取二进制文件

python - 将多态对象从 C++ 传递给 python 函数

python - 如何找到有意义的词来表示从 word2vec 向量派生的每个 k-means 聚类?

c++ - CSS设置QTableView背景色?

c++ - windbg !analyze -v 输出中的 "BUGCHECK_STR: APPLICATION_FAULT_NULL_CLASS_PTR_READ_AFTER_CALL"是什么意思

c++ - 无法在 boost-python 中导入 numpy

python - 使用 boost::python 手动构建共享对象