asc*_*bol 13 c++ python inheritance cython
我有2个班,A和B. B继承自A.
//C++
class A
{
public:
int getA() {return this->a;};
A() {this->a = 42;}
private:
int a;
};
class B: public A
{
public:
B() {this->b = 111;};
int getB() {return this->b;};
private:
int b;
};
Run Code Online (Sandbox Code Playgroud)
现在我想使用Cython连接这两个类,并且可以从B实例调用getA()方法:
a = PyA()
b = PyB()
assert a.getA() == b.getA()
Run Code Online (Sandbox Code Playgroud)
目前我的pyx文件如下所示:
cdef extern from "Inherit.h" :
cdef cppclass A:
int getA()
cdef cppclass B(A):
int getB()
cdef class PyA:
cdef A* thisptr
def __cinit__(self):
print "in A: allocating thisptr"
self.thisptr = new A()
def __dealloc__(self):
if self.thisptr:
print "in A: deallocating thisptr"
del self.thisptr
def getA(self):
return self.thisptr.getA()
cdef class PyB(PyA):
def __cinit__(self):
if self.thisptr:
print "in B: deallocating old A"
del self.thisptr
print "in B: creating new b"
self.thisptr = new B()
def __dealloc__(self):
if self.thisptr:
print "in B: deallocating thisptr"
del self.thisptr
self.thisptr = <A*>0
def getB(self):
return (<B*>self.thisptr).getB()
Run Code Online (Sandbox Code Playgroud)
虽然我希望这段代码没有做太危险的事情,但我也希望有更好的方法来处理它.
此外,使用该模块还会生成以下输出:
>>> from inherit import *
>>> b = PyB()
in A: allocating thisptr
in B: deallocating old A
in B: creating new b
>>> b.getA()
42
>>> b.getB()
111
>>> del b
in B: deallocating thisptr
Run Code Online (Sandbox Code Playgroud)
我真的不喜欢分配A实例只是为了立即释放它.
关于如何正确地做到这一点的任何建议?
我做了一些实验,并且已经准备好了答案,但现在我知道问题在哪里:
如果扩展类型具有基类型,则在
__cinit__调用__cinit__方法之前会自动调用基类型的方法; 你不能显式调用继承的__cinit__方法.
所以真正的问题是Cython类型仍然没有构造函数,只有pre initializer hook __cinit__,它的行为更像默认构造函数.你不能调用构造函数从虚方法,你不能把它从__cinit__任一(如果您拨打一个电话,它表现得像非虚拟).
不知怎的,里面__cinit__的type(self)返回正确类型的对象,但它是无用的.Cython没有静态字段,方法和类型对象只能是实例type(没有元类).Python @staticmethod很容易覆盖,所以它没用.
因此,没有其他方法可以将分配放在内部def __init__(self):,并thisptr在您使用它的任何地方检查初始化.
您可以考虑创建一个全局虚拟C++对象,并将其分配thisptr给以避免检查和崩溃.没有post initializer hook,因此您将无法检查是否已经进行了正确的初始化.