In binding a derived class must I also bind all parent classes to the root class?

Viewed 381

True or False

To bind a derived class in a C++ class hierarchy one must also bind all the parent classes on up to the root class.

I'm looking to bind a bunch of custom data types in a project I just started on and am looking to scope out the degree of work involved. I'm looking to bind a class that's 3 levels of derivation away from a root type.

Are there any rules of thumb for when one must also bind the parent classes to successfully bind the child classes?

1 Answers

False


Let us consider a simple example:

#include <string>

class Parent
{
public:
    Parent() { m_name = "Parent"; }

    std::string foo() { return m_name + "::foo"; }

    virtual std::string bar() { return m_name + "::bar"; }

protected:
    std::string m_name;
};

class Derived : public Parent
{
public:

    Derived() { m_name = "Derived"; }

    std::string bar() override { return m_name + "::bar (override)"; }
};

This you can bind the way you describe: bind the parent, the derived class will benefit from all the derived methods (you even don't have to bind the override):

#include <pybind11/pybind11.h>

namespace py = pybind11;

PYBIND11_MODULE(example, m)
{
    py::class_<Parent>(m, "Parent")
        .def(py::init<>(), "Constructor description")
        .def("foo", &Parent::foo, "Function description")
        .def("bar", &Parent::bar, "Function description")
        .def("__repr__", [](const Parent&) { return "<Parent>"; });

    py::class_<Derived, Parent>(m, "Derived")
        .def(py::init<>(), "Constructor description")
        .def("__repr__", [](const Derived&) { return "<Derived>"; });
}

Indeed

import example

p = example.Parent()
print(p.foo())
print(p.bar())

d = example.Derived()
print(d.foo())
print(d.bar())

will print

Parent::foo
Parent::bar
Derived::foo
Derived::bar (override)

However, if you just want to bind one derived class (you don't care about the parent, nor about any of the other derived classes) you can also just bind the derived class you care about, without ever specifying the parent:

#include <pybind11/pybind11.h>

namespace py = pybind11;

PYBIND11_MODULE(example, m)
{
    py::class_<Derived>(m, "Derived")
        .def(py::init<>(), "Constructor description")
        .def("foo", &Derived::foo, "Function description")
        .def("bar", &Derived::bar, "Function description")
        .def("__repr__", [](const Derived&) { return "<Derived>"; });
}

Indeed

import example

d = example.Derived()
print(d.foo())
print(d.bar())

prints

Derived::foo
Derived::bar (override)

See the docs for reference.

Related