2013-01-31 34 views
1

我正在使用Boost Python为C++中的某些类提供python接口。 我发现这个局面,我不知道如何解决:几个具有不同签名的虚拟成员函数

我有了这个成员函数的类:

virtual void visit(const ReportClass r) = 0; 
virtual void visit(const unsigned int category) = 0; 
virtual void visit(const char* type) = 0; 
virtual void visit(const char* name, const unsigned int id, const char &value) = 0; 
virtual void visit(const char* name, const unsigned int id, const unsigned short &value) = 0; 
virtual void visit(const char* name, const unsigned int id, const unsigned int &value) = 0; 
virtual void visit(const char* name, const unsigned int id, const MaskedAddr &value) = 0; 
virtual void visit(const char* name, const unsigned int id, const unsigned long long &value) = 0; 

我有点失去了对如何实现python- boost部分,我已经看到如何进行虚函数和重载函数,但我不知道如何将两者结合起来。

顺便说一下,我看到的是一个虚函数返回一个int(例如)应实施这样的例子:

int f() 
{ 
    return this->get_override("f")(); 
} 

在我的情况下,他们不返回任何我想我应该以这种方式实施:

void f() 
{ 
    this->get_override("f")(); 
} 

这是正确的吗?

在此先感谢

+3

** **乱收费的功能呢?那是什么? –

+0

对不起,超载.... – RaistlinMolina

+0

您的立场正确。 –

回答

1

如果我正确理解你的问题,你要绑定纯虚(重载)方法到Python,这样他们就可以从蟒蛇超载。你有already found的教程,部分解释。在你的具体情况下,C++和Python与超载不能很好地相互作用。虽然C++允许,但Python禁止。 Python中不能有两个名称为f的方法。我们要做的就是分歧 python调用,所以用户可以实现从Python重写。

我会写一个较小的例子,但是你可以从中抽象出来。

让我们从C++管道开始吧。您的C++绑定应如下所示:

struct BaseWrap : Base, boost::python::wrapper<Base> { 
    int f() { 
     return this->get_override("__f1__")(); 
    } 

    int f(int i) { 
     return this->get_override("__f2__")() 
    } 

    int f(const char* s) { 
     return this->get_override("__f3__")() 
    } 

    int f(const char* s, double d) { 
     return this->get_override("__f4__")() 
    } 
}; 

//your module code will look like this 
BOOST_PYTHON_MODULE(example) { 
    using namespace boost::python; 
    class_<BaseWrap, boost::noncopyable>("Base") 
    .def("f", pure_virtual(((int)(Base::*)())&Base::f)) 
    .def("f", pure_virtual(((int)(Base::*)(int))&Base::f)) 
    .def("f", pure_virtual(((int)(Base::*)(const char*))&Base::f)) 
    .def("f", pure_virtual(((int)(Base::*)(const char*, double))&Base::f)) 
    ; 
} 

我们做了什么?当代码的Python端调用f(<parameters>)时,我们将解析为正确的重载方法。然后这个方法将调用Python的__f1____f2__等,其中方法的肉实际上是从Python编码的。

要完成绑定,在Python中,你必须从example.Base继承,并实现__f1____f2____f3____f4__

class Base(example.Base): 
    """Throw here the documentation of Base - don't bother about the C++ stuff""" 

    def __init__(self,...): 
    pass 

    def __f1__(self): 
    """Implementation of Base::f()""" 
    pass 

    def __f2__(self): 
    """Implementation of Base::f(int)""" 
    pass 

    def __f3__(self): 
    """Implementation of Base::f(const char*)""" 
    pass 

    def __f4__(self): 
    """Implementation of Base::f(const char*, double)""" 
    pass 
1

让我们先来简单的问题:您可以随时“返回这个 - > get_override(” F“)();”,即使返回类型为void。实际上,在这样的包装代码中,我发现即使是更好的选择,因为如果突然包装的函数返回一些东西,你会得到一个编译错误!

现在的难题:如何在这里混合使用虚函数和重载函数。我会使用模板方法模式规避这个问题。这个想法是简单地提供一个公用的,非虚拟的函数来调用一个私有的虚函数。或者,您可以使虚拟人受到保护,以允许扩展而不是覆盖。此外,在非虚拟环境中,您可以验证派生类必须满足或验证参数的前/后条件(例如,assert(name);)。