pascalabcnet/PABCNetHelp/LangGuide/ProcFunc/overloading.html

144 lines
8.6 KiB
HTML
Raw Permalink Normal View History

<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>
&nbsp; Print(1);<br>
<b>end</b>;</code></p>
<p><code><b>begin</b><br>
&nbsp; p(2.2);<br>
&nbsp; 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>
&nbsp; Print(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>
&nbsp; Print(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>
&nbsp; Print(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>
&nbsp; Print(2);<br>
<b>end</b>;</code></p>
<p><code><b>begin</b><br>
&nbsp; p(1)&nbsp; <br>
<b>end</b>.</code></p>
</blockquote>
<p>будет вызвана первая процедура.<br>
&nbsp;</p>
</body>
</html>