Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

This is the documentation for an old version of boost. Click here for the latest Boost documentation.
Virtual Functions with Default Implementations

Recall that in the previous section, we wrapped a class with a pure virtual function that we then implemented in C++ or Python classes derived from it. Our base class:

    struct Base
    {
        virtual int f() = 0;
    };

had a pure virtual function f. If, however, its member function f was not declared as pure virtual:

    struct Base
    {
        virtual int f() { return 0; }
    };

and instead had a default implementation that returns 0, as shown above, we need to add a forwarding function that calls the Base default virtual function f implementation:

    struct BaseWrap : Base
    {
        BaseWrap(PyObject* self_)
            : self(self_) {}
        int f() { return call_method<int>(self, "f"); }
        int default_f() { return Base::f(); } // <<=== ***ADDED***
        PyObject* self;
    };

Then, Boost.Python needs to keep track of 1) the dispatch function f and 2) the forwarding function to its default implementation default_f. There's a special def function for this purpose. Here's how it is applied to our example above:

    class_<Base, BaseWrap>("Base")
        .def("f", &Base::f, &BaseWrap::default_f)

Note that we are allowing Base objects to be instantiated this time, unlike before where we specifically defined the class_<Base> with no_init.

In Python, the results would be as expected:

    >>> base = Base()
    >>> class Derived(Base):
    ...     def f(self):
    ...         return 42
    ...
    >>> derived = Derived()

Calling base.f():

    >>> base.f()
    0

Calling derived.f():

    >>> derived.f()
    42

Calling call_f, passing in a base object:

    >>> call_f(base)
    0

Calling call_f, passing in a derived object:

    >>> call_f(derived)
    42