mirror of
https://github.com/boostorg/python.git
synced 2026-01-19 16:32:16 +00:00
166 lines
5.1 KiB
HTML
166 lines
5.1 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||
<title>
|
||
Inheritance
|
||
</title>
|
||
<div>
|
||
<h1>
|
||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Inheritance
|
||
</h1>
|
||
|
||
<h2>Inheritance in Python</h2>
|
||
|
||
<p>
|
||
Py_cpp extension classes support single and multiple-inheritance in
|
||
Python, just like regular Python classes. You can mix built-in Python
|
||
classes with py_cpp extension classes in a derived class' tuple of
|
||
bases. Whenever a py_cpp extension class is among the bases for a new
|
||
class in Python, the result is an extension class:
|
||
<blockquote>
|
||
<pre>
|
||
>>> class MyPythonClass:
|
||
... def f(): return 'MyPythonClass.f()'
|
||
...
|
||
>>> import my_extension_module
|
||
>>> class Derived(my_extension_module.MyExtensionClass, MyPythonClass):
|
||
... '''This is an extension class'''
|
||
... pass
|
||
...
|
||
>>> x = Derived()
|
||
>>> x.f()
|
||
'MyPythonClass.f()'
|
||
>>> x.g()
|
||
'MyExtensionClass.g()'
|
||
</pre>
|
||
</blockquote>
|
||
|
||
<h2><a name="implicit_conversion">Reflecting C++ Inheritance Relationships</a></h2>
|
||
<p>
|
||
Py_cpp also allows us to represent C++ inheritance relationships so that
|
||
wrapped derived classes may be passed where values, pointers, or
|
||
references to a base class are expected as arguments. The
|
||
<code>declare_base</code> member function of
|
||
<code>class_builder<></code> is used to establish the relationship
|
||
between base and derived classes:
|
||
|
||
<blockquote>
|
||
<pre>
|
||
#include <memory> // for std::auto_ptr<>
|
||
|
||
struct Base {
|
||
virtual ~Base() {}
|
||
virtual const char* name() const { return "Base"; }
|
||
};
|
||
|
||
struct Derived : Base {
|
||
Derived() : x(-1) {}
|
||
virtual const char* name() const { return "Derived"; }
|
||
int x;
|
||
};
|
||
|
||
std::auto_ptr<Base> derived_as_base() {
|
||
return std::auto_ptr<Base>(new Derived);
|
||
}
|
||
|
||
const char* get_name(const Base& b) {
|
||
return b.name();
|
||
}
|
||
|
||
int get_derived_x(const Derived& d) {
|
||
return d.x;
|
||
}
|
||
<hr>
|
||
#include <boost/python/class_builder.hpp>
|
||
extern "C"
|
||
#ifdef _WIN32
|
||
__declspec(dllexport)
|
||
#endif
|
||
void initmy_module()
|
||
{
|
||
try
|
||
{
|
||
boost::python::module_builder my_module("my_module");
|
||
|
||
boost::python::class_builder<Base> base_class(my_module, "Base");
|
||
base_class.def(boost::python::constructor<void>());
|
||
|
||
boost::python::class_builder<Derived> derived_class(my_module, "Derived");
|
||
derived_class.def(boost::python::constructor<void>());
|
||
<b>// Establish the inheritance relationship between Base and Derived
|
||
derived_class.declare_base(base_class);</b>
|
||
|
||
my_module.def(derived_as_base, "derived_as_base");
|
||
my_module.def(get_name, "get_name");
|
||
my_module.def(get_derived_x, "get_derived_x");
|
||
}
|
||
catch(...)
|
||
{
|
||
boost::python::handle_exception(); // Deal with the exception for Python
|
||
}
|
||
}
|
||
</pre>
|
||
</blockquote>
|
||
|
||
<p>
|
||
Then, in Python:
|
||
<blockquote>
|
||
<pre>
|
||
>>> from my_module import *
|
||
>>> base = Base()
|
||
>>> derived = Derived()
|
||
>>> get_name(base)
|
||
'Base'
|
||
</pre><i>objects of wrapped class Derived may be passed where Base is expected</i><pre>
|
||
>>> get_name(derived)
|
||
'Derived'
|
||
</pre><i>objects of wrapped class Derived can be passed where Derived is
|
||
expected but where type information has been lost.</i><pre>
|
||
>>> get_derived_x(derived_as_base())
|
||
-1
|
||
</pre>
|
||
</blockquote>
|
||
|
||
<h2>Inheritance Without Virtual Functions</h2>
|
||
|
||
<p>
|
||
If for some reason your base class has no virtual functions but you still want
|
||
to represent the inheritance relationship between base and derived classes,
|
||
pass the special symbol <code>boost::python::without_downcast</code> as the 2nd parameter
|
||
to <code>declare_base</code>:
|
||
|
||
<blockquote>
|
||
<pre>
|
||
struct Base2 {};
|
||
struct Derived2 { int f(); };
|
||
<hr>
|
||
...
|
||
boost::python::class_builder<Base> base2_class(my_module, "Base2");
|
||
base2_class.def(boost::python::constructor<void>());
|
||
|
||
boost::python::class_builder<Derived2> derived2_class(my_module, "Derived2");
|
||
derived2_class.def(boost::python::constructor<void>());
|
||
derived_class.declare_base(base_class, <b>boost::python::without_downcast</b>);
|
||
</pre>
|
||
</blockquote>
|
||
|
||
<p>This approach will allow <code>Derived2</code> objects to be passed where
|
||
<code>Base2</code> is expected, but does not attempt to implicitly convert (downcast)
|
||
smart-pointers to <code>Base2</code> into <code>Derived2</code> pointers,
|
||
references, or values.
|
||
|
||
<p>
|
||
Previous: <a href="overloading.html">Function Overloading</a>
|
||
Next: <a href="special.html">Special Method Names</a>
|
||
Up: <a href="index.html">Top</a>
|
||
<p>
|
||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||
sell and distribute this document is granted provided this copyright
|
||
notice appears in all copies. This document is provided "as is" without
|
||
express or implied warranty, and with no claim as to its suitability
|
||
for any purpose.
|
||
<p>
|
||
Updated: Nov 26, 2000
|
||
</div>
|
||
|