144 lines
5.9 KiB
HTML
144 lines
5.9 KiB
HTML
<html>
|
||
|
||
<head>
|
||
<object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
|
||
<param name="Keyword" value="Перегрузка имен">
|
||
<param name="Keyword" value="overload">
|
||
</object>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
|
||
<title></title>
|
||
<link rel="StyleSheet" href="../../default.css">
|
||
</head>
|
||
|
||
<body>
|
||
<H1>Перегрузка имен подпрограмм</H1>
|
||
<p>В одном <a href="../_ProgrStruct_Defs/scope.html">пространстве имен</a> может быть определено
|
||
несколько процедур или функций с одним именем, но разным количеством или типами
|
||
параметров. Имена таких процедур и функций называются перегруженными, а их
|
||
создание - <b><font color="#FF0000"> <i>перегрузкой имен</i></font></b>.
|
||
Разновидностью перегрузки имен является
|
||
<a href="../Classes/operoverloading.html">перегрузка операций</a>.</p>
|
||
<p>При вызове перегруженной процедуры или функции выбирается
|
||
та версия, у которой типы формальных параметров совпадают с типами фактических
|
||
или наиболее близки к ним. Например, если имеются описания </p>
|
||
<blockquote>
|
||
<p><code><b>procedure </b>p(b: byte);<b><br>
|
||
begin</b><br><b>end</b>;<b><br>
|
||
procedure </b>p(r: real);<b><br>
|
||
begin</b><br><b>end</b>;</code></p>
|
||
</blockquote>
|
||
<p>то при вызове <code>p(1.0)</code> будет выбрана перегруженная
|
||
версия с параметром типа <code>real</code> (точное
|
||
соответствие), а при вызове <code>p(1)</code> будет
|
||
выбрана перегруженная версия с параметром типа <code>byte</code> (при
|
||
этом произойдет преобразование фактического параметра типа <code>integer</code>
|
||
к типу <code>byte</code>).</p>
|
||
<p>Заметим, что, в отличие от Object Pascal, использовать при
|
||
перегрузке служебное слово <code><b>overload</b></code> не нужно.</p>
|
||
<p>Если ни одна версия в текущем пространстве имен не подходит к
|
||
данному вызову, то возникает ошибка компиляции. Если две и более версии одинаково хорошо подходят к данному вызову, то
|
||
также возникает ошибка компиляции,
|
||
заключающаяся в неоднозначности выбора подпрограммы.
|
||
Например, если имеются описания</p>
|
||
<blockquote>
|
||
<p><code><b>procedure </b>p(i: integer; r: real);<b><br>
|
||
begin</b><br><b>end</b>;<b><br>
|
||
procedure </b>p(r: real; i: integer);<b><br>
|
||
begin</b><br><b>end</b>;</code></p>
|
||
</blockquote>
|
||
<p>то при вызове <code>p(1,2)</code> оба
|
||
они одинаково подходят, что приводит к неоднозначности.</p>
|
||
<p>Запрещено перегружать подпрограмму другой подпрограммой с тем
|
||
же количеством и типами параметров, отличающихся лишь тем,
|
||
передается ли параметр по значению или по ссылке. Например, описания</p>
|
||
<blockquote>
|
||
<p><code><b>procedure</b> p(i: integer);</code></p>
|
||
</blockquote>
|
||
<p>и</p>
|
||
<blockquote>
|
||
<p><code><b>procedure</b> p(<b>var</b> i: integer);</code></p>
|
||
</blockquote>
|
||
<p>считаются одинаковыми.</p>
|
||
<p>Возвращаемое значение функции не участвует в
|
||
разрешении перегрузки, т.е. перегружаемые функции не могут различаться
|
||
только типами возвращаемых значений.</p>
|
||
<p>Алгоритм перегрузки имен при наличии нескольких подключенных
|
||
модулей, а также алгоритм перегрузки имен методов имеют особенности. Основная особенность этих
|
||
алгоритмов состоит в том, что они работают через границы пространств имен.</p>
|
||
<p>Поиск перегруженного
|
||
имени глобальной подпрограммы при наличии нескольких
|
||
подключенных модулей происходит во всех
|
||
модулях. При этом вначале осуществляется просмотр текущего модуля, а потом всех
|
||
модулей, подключенных в секции <code><b>uses</b></code>,
|
||
в порядке <i>справа налево</i>. Если при этом поиске находится объект, который
|
||
не может перегружать предыдущие (например, перегружается процедура, а найдено
|
||
имя переменной), то цепочка перегрузки заканчивается, и поиск наилучшей
|
||
перегруженной подпрограммы идет среди найденных до этого момента. Если в модуле,
|
||
откомпилированном позже, имеется подпрограмма с точно такими же параметрами, то
|
||
она скрывает версию из модуля, откомпилированного раньше. </p>
|
||
<p>Например, пусть основная программа подключает два модуля -
|
||
<code>un1</code> и <code>un2</code>:</p>
|
||
<p><b><font size="2">main.pas</font></b></p>
|
||
<blockquote>
|
||
<p><code><b>uses</b> un2,un1;</code></p>
|
||
<p><code><b>procedure</b> p(i: integer);<br>
|
||
<b>begin</b><br>
|
||
write(1);<br>
|
||
<b>end</b>;</code></p>
|
||
<p><code><b>begin</b><br>
|
||
p(2.2);<br>
|
||
p(2);<br>
|
||
<b>end</b>.</code></p>
|
||
</blockquote>
|
||
<p><b><font size="2">un2.pas</font></b></p>
|
||
<blockquote>
|
||
<p><code><b>unit</b> un2;</code></p>
|
||
<p><code><b>procedure</b> p(r: real);<br>
|
||
<b>begin</b><br>
|
||
write(3);<br>
|
||
<b>end</b>;</code></p>
|
||
<p><code><b>end</b>.</code></p>
|
||
</blockquote>
|
||
<p><b><font size="2">un1.pas</font></b></p>
|
||
<blockquote>
|
||
<p><code><b>unit</b> un1;</code></p>
|
||
<p><code><b>procedure</b> p(r: real);<br>
|
||
<b>begin</b><br>
|
||
write(2);<br>
|
||
<b>end</b>;</code></p>
|
||
<p><code><b>end</b>.</code></p>
|
||
</blockquote>
|
||
<p>В результате будет выведено <code>21</code>,
|
||
что означает, что первой была вызвана процедура <code>p</code>
|
||
из модуля <code>un1</code>.</p>
|
||
<p>Поиск перегруженного имени метода осуществляется аналогично:
|
||
вначале осуществляется просмотр текущего класса, затем его базового класса и
|
||
т.д. до класса <code>Object</code>, либо до того момента, как будет встречен
|
||
объект, который не может перегружать предыдущие (имя поля или
|
||
свойства). Из всех найденных таким образом одноименных методов выбирается
|
||
наилучший. При этом в
|
||
разных классах могут быть методы с идентичными параметрами;
|
||
в этом случае вызывается первый встреченный метод от данного
|
||
класса к классу <code>Object</code>. </p>
|
||
<p>Подпрограммы с переменным числом параметров
|
||
также участвуют в перегрузке, однако, обычные подпрограммы имеют над ними
|
||
приоритет. Например, в ситуации</p>
|
||
<blockquote>
|
||
<p><code><b>procedure</b> p(i: integer);<br>
|
||
<b>begin</b><br>
|
||
write(1);<br>
|
||
<b>end</b>;</code></p>
|
||
<p><code><b>procedure</b> p(<b>params</b> a: <b>array</b> <b>of</b>
|
||
integer);<br>
|
||
<b>begin</b><br>
|
||
write(2);<br>
|
||
<b>end</b>;</code></p>
|
||
<p><code><b>begin</b><br>
|
||
p(1) <br>
|
||
<b>end</b>.</code></p>
|
||
</blockquote>
|
||
<p>будет вызвана первая процедура.<br>
|
||
</p>
|
||
</body>
|
||
|
||
</html> |