多重继承/虚函数

时间:2015-02-17 22:03:37

标签: python c++ inheritance virtual cython

使用Cython(充当接口,因此我可以通过Python调用基于C ++的函数),我试图包含一个复杂的C ++类层次结构,所有这些都最终从一个基类继承。这个单一的基类有许多虚函数,它们的实现基于所考虑的派生类而不同。派生类也有自己独特的功能。

我在通过Cython包装它时遇到了很多麻烦,主要是因为我无法找到一种方法来重新定义每个继承类中的 self.thisptr 属于该特定类型(而不是单数基类的类型)。我也尝试过类型转换,以及尝试删除指针然后重新初始化它,但它仍然认为它指向同一个基类。示例代码如下:

inheritTest.pyx:

cdef extern from "BaseClass.h":
    cdef cppclass BaseClass:
        BaseClass() except +
        void SetName(string)
        float Evaluate(float)
        bool DataExists()

cdef extern from "DerivedClass.h":
    cdef cppclass DerivedClass(BaseClass):
        DerivedClass() except +
        void MyFunction()
        float Evaluate(float)
        bool DataExists()
        SetObject(BaseClass *)

cdef class PyBaseClass:
    cdef BaseClass *thisptr
    def __cinit__(self):
        self.thisptr = new BaseClass()
    def __dealloc__(self):
        del self.thisptr

cdef class PyDerivedClass(PyBaseClass):
    #This is one of the solutions that I have tried
    def __cinit__(self):
        if(self.thisptr):
            del self.thisptr
        self.thisptr = new DerivedClass()
    def __dealloc__(self):
        del self.thisptr
    def Evaluate(self, time):
        #I need to call the Derived implementation of this function, not Base
        return self.thisptr.Evaluate(self,time)
    def SetObject(self, PyBaseClass inputObject):
         #The issue here is that it looks for SetObject to be declared in BaseClass and spits an error otherwise. If I put a empty declaration, the complain is of ambiguous method overload
         self.thisptr.SetObject(inputObject.thisptr)

另外,当我在Python脚本中调用SetObject时,我希望能够传入PyDerived对象作为输入,因为它继承自PyBase,它不应该只是工作吗?我试过了,错误就是:

参数类型不正确:预期PyBase,得到PyDerived

希望我的问题有意义,如果您需要任何其他信息,请告诉我:)

1 个答案:

答案 0 :(得分:1)

如果self.thisptr的类型是基类,只需使基类的构造函数初始化指针,而不是删除self的旧副本。

def __cinit__(self):
    if type(self) is PyBaseClass:
        self.thisptr = new BaseClass()

请确保在基类__dealloc__方法中以相同的方式防止重新分配。

然后,为了避免一堆不必要的强制转换,在子类包装器中,创建两个不同的属性,一个存储指向c ++对象的指针转换为基类的类型,另一个存储指向c ++对象的指针它的原始类型。像这样:

cdef DerivedClass* derivedptr
def __cinit__(self):
    self.derivedptr = self.thisptr = new DerivedClass()

然后,当您需要访问派生类的方法时,请改用派生指针。

确保在解除分配时,只删除派生指针。

我从Cython Users mailing list的讨论中得到了这个想法。