русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

При обращении внутри функции к значению аргумента через параметр-указатель необходимо осуществить разыменование этого указателя.


Дата добавления: 2014-04-05; просмотров: 880; Нарушение авторских прав


Несколько проще обстоит дело с передачей массивов, так как переменные типа массив сами являются указателями на первый элемент массива. В связи с этим отпадает необходимость в выполнении пунктов 2 и 3 из перечисленных выше. Рассмотрим пример:

 



void ReadArr ( int *P, int n)

{

for (int I = 0; I < n; ++I)

cin >> P[I];

}

 



void WriteArr ( int Arr[], int n)

{

for (int I = 0; I < n; ++I)

cout << Arr[I] << “ “;

cout << endl;

}

 



int main()

{

const n = 10;

int A[n];

ReadArr (A, n);

WriteArr (A, n);

return 0;

}

 



В первой функции параметр для передачи массива определен как указатель на тип int, то есть через этот параметр может быть передан адрес первого элемента массива.

Во второй функции параметр для передачи массива определен как массив из элементов типа int, но это одновременно и указатель на первый элемент массива.

Внутри первой функции при обращении к очередному элементу массива никакого разыменования указателя не требуется, так как указатели могут индексироваться непосредственно.

Во второй функции при обращении к очередному элементу массива также не требуется разыменовывать параметр Arr – обращение к ним осуществляется естественным для массива способом – с помощью индексации элементов.

Кода осуществляется вызов этих функций, определять адрес аргумента для параметра–массива необходимости нет, так как переменная A сама является адресом первого элемента массива.

Таким образом, оба эти способа передачи массивов являются эквивалентными и оба они допускают передачу измененных внутри функции значений элементов массива в вызывающую часть программы.

Поскольку строки символов являются массивами, их передача в функции осуществляется так же, как и обычных массивов. Например:

 



void StringProc(char * S, int L)

 



или

 



void StringProc(char S[], int L)

 



Этот способ передачи данных часто называют передачей данных по адресу.

Передача данных по ссылке

Передача данных с использованием указателей несколько трудоемка, поскольку требует при вызове функций передавать адрес аргумента, а внутри функции разыменовывать параметры-указатели. Кроме того, неправильное выполнение этих дополнительных действий может привести к появлению ошибок.

В языке C++ имеется более простой способ передачи данных по адресу, а именно – передача данных по ссылке.

Переделаем пример предыдущего параграфа так, чтобы данные в нем передавались не через указатель, а по ссылке:

 



int Div (int N1, int N2, int &Ost) // int &Ost – параметр-ссылка

{

Ost = N1 % N2; // Разыменования параметра-ссылки Ost не требуется

return N1 / N2;

}

 



int main()

{

int I = 10, J = 3, R, O;

R = Div (I, J, O); // Используется сам аргумент О, а не его адрес

cout << I << “ / ” << J << “ = ” << R << “. Остаток равен “ << O << endl;

return 0;

}

 



Из этого примера видно, что для определения параметра, с помощью которого функция может вернуть остаток от деления, используется символ &, а не *. Именно так определяются параметры-ссылки. Внутри процедуры, для получения доступа к значению данных, разыменовывать параметр-ссылку не нужно. При вызове процедуры используется сам аргумент, а не его адрес. Таким образом, использование передачи данных по ссылке значительно проще, чем передача данных через указатели.

На самом деле в этом способе передача данных осуществляется точно так же, как и при использовании указателей, только операции взятия адреса аргумента и разыменования параметра-ссылки осуществляется компилятором автоматически, скрытно от нас.

Способ передачи данных по ссылке также можно отнести к передаче данных по адресу, и он полностью эквивалентен по своему эффекту передачи данных через указатели.

В целом, передача данных по адресу (с помощью указателей или по ссылке), является более эффективной, чем передача данных по значению. Это объясняется тем, что при передаче данных по значению осуществляется создание копии аргумента функции, а на это тратится и память и время. При передаче по адресу затраты памяти и времени существенно меньше, так как в функцию передается только адрес данных, а не сами данные, объем которых часто существенно превышает размер адреса.

Возникает вопрос: почему всегда не использовать передачу данных по адресу, поскольку это более эффективно? Недостатком передачи данных по адресу является скрытый побочный эффект, связанный с возможным непредвиденным изменением внутри функции значения аргумента переданного по адресу. Однако этого эффекта можно избежать, если определить соответствующий параметр функции как константу:

 



void Proc(const double *D)

{

……

*D = 3.14; // Ошибка в процессе компиляции

……

}

Перегружаемые функции

Поскольку при вызове функций типы данных подставляемых аргументов и их количество должны соответствовать типам данных и количеству параметров функций, в языке C приходилось использовать множество функций с различными именами для выполнения одних и тех же действий над различными типами данных. Например, для вычисления абсолютного значения некоторого числа в библиотеках языка C имелось несколько различных функций: abs, labs, fabs, fadsf. Использование этих функций определялось типами данных обрабатываемых чисел. Но все они выполняли одно и то же действие – вычисляли абсолютное значение аргумента. Это доставляло определенные неудобства.

В языке C++ появилось понятие перегруженных (перегружаемых) функций, которое позволило избавиться от этого неудобства.

Перегруженными функциями называются функции, имеющие одинаковые имена, но различающиеся количеством, типами данных или порядком следования разнотипных параметров. Например:

 



void f (char c)

{

…….

}

 



void f (int c)

{

…….

}

 



int f (char c, int i)

{

…….

}

 



void f (int c, char i)

{

…….

}

 



void f (char c, char i)

{

…….

}

 



При вызове таких функций компилятор сам определяет, какую из этих функций необходимо использовать применительно к использованному при вызове списку аргументов. Чтобы у компилятора не возникало “сомнений” по поводу выбора подходящего варианта перегруженной функции, списки параметров перегруженных функций должны однозначно различаться.

Нельзя перегружать функции, различающиеся только типами данных возвращаемых значений. Например, компилятор “не разрешит” перегрузить следующую функцию:

int f (char c, char i)

{

…….

}

 



Это объясняется тем, что функции можно вызывать без использования возвращаемого функцией значения. При таком вызове функций с совпадающим списком параметров компилятор не сможет определить, какую из функций использовать.

Параметры по умолчанию

Еще одна интересная возможность при работе с функциями состоит в использовании параметров по умолчанию.

Рассмотрим пример:

 



void F (int I, double D, char C = ’a’, int J = 10)

{

cout << C << “ “ << J << endl;

}

 



int main ()

{

F (0, 3.14); // Результат: а 10

F (0, 3.14, ’G’); // Результат: G 10

F (0, 3.14, ’G’, 1000); // Результат: G 1000

}

 



В этом примере в функции F последние два параметра определены как параметры по умолчанию.

При вызове функций имеющих параметры по умолчанию вместо них аргументы можно не подставлять. В этом случае внутри функции в качестве значений параметров будут использованы те значения, которые были заданы в заголовке функции. В том случае, если при вызове функции на место параметра по умолчанию будет подставлен некоторый аргумент, то внутри функции в качестве значения параметра по умолчанию будет использовано значение аргумента.

Количество параметров по умолчанию может быть любым. При использовании параметров по умолчанию необходимо помнить:

Все параметры по умолчанию должны находиться в конце списка параметров функции;



<== предыдущая лекция | следующая лекция ==>
Соответствующий параметр в заголовке функции необходимо определить как указатель на тип данных аргумента. | Если при вызове функции не указывается аргумент для некоторого параметра по умолчанию, то и все следующие аргументы должны быть пропущены.


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.179 сек.