2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-19 16:32:16 +00:00
Files
python/doc/inheritance.html
Dave Abrahams 2e5d8dbff7 This commit was generated by cvs2svn to compensate for changes in r711,
which included commits to RCS files with non-trunk default branches.


[SVN r8328]
2000-11-26 15:49:26 +00:00

166 lines
5.1 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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>
&gt;&gt;&gt; class MyPythonClass:
... def f(): return 'MyPythonClass.f()'
...
&gt;&gt;&gt; import my_extension_module
&gt;&gt;&gt; class Derived(my_extension_module.MyExtensionClass, MyPythonClass):
... '''This is an extension class'''
... pass
...
&gt;&gt;&gt; x = Derived()
&gt;&gt;&gt; x.f()
'MyPythonClass.f()'
&gt;&gt;&gt; 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&lt;&gt;</code> is used to establish the relationship
between base and derived classes:
<blockquote>
<pre>
#include &lt;memory&gt; // for std::auto_ptr&lt;&gt;
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&lt;Base&gt; derived_as_base() {
return std::auto_ptr&lt;Base&gt;(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&lt;Base&gt; base_class(my_module, "Base");
       base_class.def(boost::python::constructor&lt;void&gt;());
       boost::python::class_builder&lt;Derived&gt; derived_class(my_module, "Derived");
       derived_class.def(boost::python::constructor&lt;void&gt;());
<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>
&gt;&gt;&gt; from my_module import *
&gt;&gt;&gt; base = Base()
&gt;&gt;&gt; derived = Derived()
&gt;&gt;&gt; get_name(base)
'Base'
</pre><i>objects of wrapped class Derived may be passed where Base is expected</i><pre>
&gt;&gt;&gt; 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>
&gt;&gt;&gt; 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&lt;Base&gt; base2_class(my_module, "Base2");
   base2_class.def(boost::python::constructor&lt;void&gt;());
   boost::python::class_builder&lt;Derived2&gt; derived2_class(my_module, "Derived2");
   derived2_class.def(boost::python::constructor&lt;void&gt;());
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>
&copy; 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>