在我正在开发的游戏中,我有两个 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<...>
的类型。不检查虚拟继承。
虽然不可扩展并且可能表明可能值得研究基于组合的解决方案,但一个简单的继承解决方案是公开一个 CollidableSprite
从 ICollidableWrap
继承的 C++ 类和 Sprite
,然后让 Python 类继承自 CollidableSprite
.
这是一个基本示例,其中类 C
继承自 B
和 A
该虚拟继承自 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/