summaryrefslogtreecommitdiff
path: root/ext/pybind11/docs/classes.rst
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pybind11/docs/classes.rst')
-rw-r--r--ext/pybind11/docs/classes.rst69
1 files changed, 62 insertions, 7 deletions
diff --git a/ext/pybind11/docs/classes.rst b/ext/pybind11/docs/classes.rst
index 30fb2a2d5..ca2477e83 100644
--- a/ext/pybind11/docs/classes.rst
+++ b/ext/pybind11/docs/classes.rst
@@ -27,15 +27,11 @@ The binding code for ``Pet`` looks as follows:
namespace py = pybind11;
- PYBIND11_PLUGIN(example) {
- py::module m("example", "pybind11 example plugin");
-
+ PYBIND11_MODULE(example, m) {
py::class_<Pet>(m, "Pet")
.def(py::init<const std::string &>())
.def("setName", &Pet::setName)
.def("getName", &Pet::getName);
-
- return m.ptr();
}
:class:`class_` creates bindings for a C++ *class* or *struct*-style data
@@ -229,8 +225,8 @@ just brings them on par.
.. _inheritance:
-Inheritance
-===========
+Inheritance and automatic upcasting
+===================================
Suppose now that the example consists of two data structures with an
inheritance relationship:
@@ -287,6 +283,65 @@ expose fields and methods of both types:
>>> p.bark()
u'woof!'
+The C++ classes defined above are regular non-polymorphic types with an
+inheritance relationship. This is reflected in Python:
+
+.. code-block:: cpp
+
+ // Return a base pointer to a derived instance
+ m.def("pet_store", []() { return std::unique_ptr<Pet>(new Dog("Molly")); });
+
+.. code-block:: pycon
+
+ >>> p = example.pet_store()
+ >>> type(p) # `Dog` instance behind `Pet` pointer
+ Pet # no pointer upcasting for regular non-polymorphic types
+ >>> p.bark()
+ AttributeError: 'Pet' object has no attribute 'bark'
+
+The function returned a ``Dog`` instance, but because it's a non-polymorphic
+type behind a base pointer, Python only sees a ``Pet``. In C++, a type is only
+considered polymorphic if it has at least one virtual function and pybind11
+will automatically recognize this:
+
+.. code-block:: cpp
+
+ struct PolymorphicPet {
+ virtual ~PolymorphicPet() = default;
+ };
+
+ struct PolymorphicDog : PolymorphicPet {
+ std::string bark() const { return "woof!"; }
+ };
+
+ // Same binding code
+ py::class_<PolymorphicPet>(m, "PolymorphicPet");
+ py::class_<PolymorphicDog, PolymorphicPet>(m, "PolymorphicDog")
+ .def(py::init<>())
+ .def("bark", &PolymorphicDog::bark);
+
+ // Again, return a base pointer to a derived instance
+ m.def("pet_store2", []() { return std::unique_ptr<PolymorphicPet>(new PolymorphicDog); });
+
+.. code-block:: pycon
+
+ >>> p = example.pet_store2()
+ >>> type(p)
+ PolymorphicDog # automatically upcast
+ >>> p.bark()
+ u'woof!'
+
+Given a pointer to a polymorphic base, pybind11 performs automatic upcasting
+to the actual derived type. Note that this goes beyond the usual situation in
+C++: we don't just get access to the virtual functions of the base, we get the
+concrete derived type including functions and attributes that the base type may
+not even be aware of.
+
+.. seealso::
+
+ For more information about polymorphic behavior see :ref:`overriding_virtuals`.
+
+
Overloaded methods
==================