На этом шаге мы изучим относительно новый класс функций, количество
параметров у которых
становится известным только в момент обращения к этой функции.
В языке C++ допустимы функции, у которых количество параметров и их типы при компиляции определения функции не определены. Эти значения становятся известными только в момент вызова функции, когда явно задан список фактических параметров. При определении и описании таких функций, имеющих списки параметров неопределенной длины, спецификация формальных параметров заканчивается многоточием. Формат прототипа функции с переменным списком параметров:
<тип функции> <имя функции> (<спецификация явных параметров>,...); .
Здесь спецификация явных параметров - список спецификаций отдельных параметров, количество и типы которых фиксированы и известны в момент компиляции. Эти параметры называются обязательными. После списка явных (обязательных) параметров ставится необязательная запятая, а затем многоточие, извещающее компилятор, что дальнейший контроль соответствия количества и типов параметров при обработке вызова функции проводить не нужно.
Каждая функция с переменным списком параметров должна иметь механизм определения их количества и типов. Существует два подхода к решению этой задачи.
Первый подход предполагает добавление в конец списка реально k использованных необязательных фактических параметров специального параметра-индикатора с уникальным значением, которое будет сигнализировать об окончании списка. В теле функции параметры последовательно перебираются, и их значения сравниваются с заранее известным концевым признаком.
Второй подход предусматривает передачу в функцию значения реального количества фактических параметров. Значение реального количества используемых фактических параметров можно передавать в функцию с помощью одного из явно задаваемых (обязательных) параметров.
В обоих подходах - и при задании концевого признака, и при указании числа реально используемых фактических параметров - переход от одного фактического параметра к другому выполняется с помощью указателей, то есть с использованием адресной арифметики. Проиллюстрируем сказанное примерами.
#include <iostream.h> void main() { long summa (int,...); //Прототип функции. cout << "\n summa(2,4,6)=" << summa (2,4,6); cout << "\n summa(6,1,2,3,4,5,6)=" << summa (6,1,2,3,4,5,6); } long summa (int k,...) //Передаем количество параметров. { int *pk=&k; //pk содержит адрес расположения начала списка параметров. long sm=0; for (;k;k--) sm+=*(++pk); return sm; }
Комментарии к программе. В обычном случае при описании функции задается список переменных - набор формальных параметров, используя которые осуществляется доступ к переданным значениям. Здесь такого списка нет. Каким же образом получить доступ к перечню переданных параметров? Это осуществляется с помощью указателей:
#include<iostream.h> long summa (int k,...) { int *pk=&k; long sm=0; for (;*pk;) sm+=*(pk++); return sm; } void main() //Прототип функции sum отсутствует. { cout << "\n summa(4,6,0)="<< summa (4,6,0); cout << "\n summa(1,2,3,4,5,6,0)=" << summa (1,2,3,4,5,6,0); cout << "\n summa(1,2,0,4,5,6,0)=" << summa (1,2,0,4,5,6,0); }
В последнем случае на экран будет выведено число 3, так как суммируются только числа 1 и 2.
На следующем шаге мы поговорим о подставляемых функциях.