mirror of
https://github.com/boostorg/python.git
synced 2026-01-19 16:32:16 +00:00
156 lines
5.4 KiB
HTML
156 lines
5.4 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||
<title>
|
||
Function Overloading
|
||
</title>
|
||
<div>
|
||
<h1>
|
||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Function Overloading
|
||
</h1>
|
||
|
||
<h2>An Example</h2>
|
||
<p>
|
||
To expose overloaded functions in Python, simply <code>def()</code> each
|
||
one with the same Python name:
|
||
<blockquote>
|
||
<pre>
|
||
inline int f1() { return 3; }
|
||
inline int f2(int x) { return x + 1; }
|
||
|
||
class X {
|
||
public:
|
||
X() : m_value(0) {}
|
||
X(int n) : m_value(n) {}
|
||
int value() const { return m_value; }
|
||
void value(int v) { m_value = v; }
|
||
private:
|
||
int m_value;
|
||
};
|
||
...
|
||
|
||
BOOST_PYTHON_MODULE_INIT(overload_demo)
|
||
{
|
||
try
|
||
{
|
||
boost::python::module_builder overload_demo("overload_demo");
|
||
// Overloaded functions at module scope
|
||
overload_demo.def(f1, "f");
|
||
overload_demo.def(f2, "f");
|
||
|
||
boost::python::class_builder<X> x_class(overload_demo, "X");
|
||
// Overloaded constructors
|
||
x_class.def(boost::python::constructor<>());
|
||
x_class.def(boost::python::constructor<int>());
|
||
|
||
// Overloaded member functions
|
||
x_class.def((int (X::*)() const)&X::value, "value");
|
||
x_class.def((void (X::*)(int))&X::value, "value");
|
||
...
|
||
</pre>
|
||
</blockquote>
|
||
|
||
<p>
|
||
Now in Python:
|
||
<blockquote>
|
||
<pre>
|
||
>>> from overload_demo import *
|
||
>>> x0 = X()
|
||
>>> x1 = X(1)
|
||
>>> x0.value()
|
||
0
|
||
>>> x1.value()
|
||
1
|
||
>>> x0.value(3)
|
||
>>> x0.value()
|
||
3
|
||
>>> X('hello')
|
||
TypeError: No overloaded functions match (X, string). Candidates are:
|
||
void (*)()
|
||
void (*)(int)
|
||
>>> f()
|
||
3
|
||
>>> f(4)
|
||
5
|
||
</pre>
|
||
</blockquote>
|
||
|
||
<h2>Discussion</h2>
|
||
<p>
|
||
Notice that overloading in the Python module was produced three ways:<ol>
|
||
<li>by combining the non-overloaded C++ functions <code>int f1()</code>
|
||
and <code>int f2(int)</code> and exposing them as <code>f</code> in Python.
|
||
<li>by exposing the overloaded constructors of <code>class X</code>
|
||
<li>by exposing the overloaded member functions <code>X::value</code>.
|
||
</ol>
|
||
<p>
|
||
Techniques 1. and 3. above are really alternatives. In case 3, you need
|
||
to form a pointer to each of the overloaded functions. The casting
|
||
syntax shown above is one way to do that in C++. Case 1 does not require
|
||
complicated-looking casts, but may not be viable if you can't change
|
||
your C++ interface. N.B. There's really nothing unsafe about casting an
|
||
overloaded (member) function address this way: the compiler won't let
|
||
you write it at all unless you get it right.
|
||
|
||
<h2>An Alternative to Casting</h2>
|
||
<p>
|
||
This approach is not neccessarily better, but may be preferable for some
|
||
people who have trouble writing out the types of (member) function
|
||
pointers or simply prefer to avoid all casts as a matter of principle:
|
||
<blockquote>
|
||
<pre>
|
||
// Forwarding functions for X::value
|
||
inline void set_x_value(X& self, int v) { self.value(v); }
|
||
inline int get_x_value(X& self) { return self.value(); }
|
||
...
|
||
// Overloaded member functions
|
||
x_class.def(set_x_value, "value");
|
||
x_class.def(get_x_value, "value");
|
||
</pre>
|
||
</blockquote>
|
||
<p>Here we are taking advantage of the ability to expose C++ functions at
|
||
namespace scope as Python member functions.
|
||
|
||
<h2>Overload Resolution</h2>
|
||
<p>
|
||
The function overload resolution mechanism works as follows:
|
||
|
||
<ul>
|
||
|
||
<li>Attribute lookup for extension classes proceeds in <a
|
||
href="http://www.python.org/doc/current/tut/node11.html#SECTION0011510000000000000000">the
|
||
usual Python way</a> using a depth-first, left-to-right search. When a
|
||
class is found which has a matching attribute, only functions overloaded
|
||
in the context of that class are candidates for overload resolution. In
|
||
this sense, overload resolution mirrors the C++ mechanism, where a name
|
||
in a derived class ``hides'' all functions with the same name from a base
|
||
class.
|
||
<p>
|
||
|
||
<li>Within a name-space context (extension class or module), overloaded
|
||
functions are tried in the same order they were
|
||
<code>def()</code>ed. The first function whose signature can be made to
|
||
match each argument passed is the one which is ultimately called.
|
||
This means in particular that you cannot overload the same function on
|
||
both ``<code>int</code>'' and ``<code>float</code>'' because Python
|
||
automatically converts either of the two types into the other one.
|
||
If the ``<code>float</code>'' overload is found first, it is used
|
||
also used for arguments of type ``<code>int</code>'' as well, and the
|
||
``<code>int</code>'' version of the function is never invoked.
|
||
</ul>
|
||
|
||
<p>
|
||
Next: <a href="inheritance.html">Inheritance</a>
|
||
Previous: <a href="overriding.html">Overridable Virtual Functions</a>
|
||
Up: <a href="index.html">Top</a>
|
||
<p>
|
||
© Copyright David Abrahams 2001. 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: Mar 6, 2001
|
||
</div>
|
||
|