[C++-sig] how to call base class method?

Jim Bosch talljimbo at gmail.com
Sat May 7 04:24:41 CEST 2011


On 05/06/2011 06:51 PM, zeb wrote:
> I have 2 class exposed to python:
> class A {
> public:
>      virtual int get() { return 1; }
> };
>
> class B : public A {
> public:
>      virtual int get() { return 2; }
> };
>
> In python:
> obj = B()
> obj.get() # this will call B's get()
>
> For some reason, I want to call A's get() in python, like obj->A::get() in
> C++. So I have tried:
> @ Directly call base class's method in python: A.get(obj) # failed.
> @ make a wrap function to cast B to A:
> A* cast(B* obj) {
>      return (A*)obj;
> }
> And try to use different call policy, like manage_new_object,
> reference_existing_object, return_internal_reference, but all failed.
> After casting, the two object actually the same object.
>>>> objB = B()
>>>> objA = cast(objB)
>>>> objA == objB
> True
>

The fact that you never get back an "A" Python object is very much a 
feature rather than a bug, and while you might be able to find a way 
around it, it's not recommended.

If this wasn't a virtual member function, you could have used the usual 
Python syntax for a base class method call:

obj = B()
A.get(obj)  # should return 1, if "get" isn't virtual

For a virtual member function, I don't think there's a way to do this 
without wrapping the base class method separately, and even that 
requires some extra work.  I think something like this may do what you want:

int A_get(A & self) {
     return self.A::get();
}

class_<A>("A")
     .def("A_get", &A_get)
     .def("get", &A::get)
     ;

You could also wrap "A_get" directly as "get" in class A, which should 
allow you to use the "A.get(obj)" successfully, I think, but you might 
want to make sure that it doesn't also destroy the usual (virtual) 
behavior of the method in Python.


Jim




More information about the Cplusplus-sig mailing list