mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 14:45:12 +00:00
Document automatic upcasting of polymorphic types (#654)
Resolves #645.
This commit is contained in:
parent
2e37fe09e1
commit
7c0e2c247b
@ -225,8 +225,8 @@ just brings them on par.
|
|||||||
|
|
||||||
.. _inheritance:
|
.. _inheritance:
|
||||||
|
|
||||||
Inheritance
|
Inheritance and automatic upcasting
|
||||||
===========
|
===================================
|
||||||
|
|
||||||
Suppose now that the example consists of two data structures with an
|
Suppose now that the example consists of two data structures with an
|
||||||
inheritance relationship:
|
inheritance relationship:
|
||||||
@ -283,6 +283,65 @@ expose fields and methods of both types:
|
|||||||
>>> p.bark()
|
>>> p.bark()
|
||||||
u'woof!'
|
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
|
Overloaded methods
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user