Язык программирования C++. Вводный курс

Многоточие


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

void foo( parm_list, ... );

void foo( ... );

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

Примером вынужденного использования многоточия служит функция printf()

стандартной библиотеки С. Ее первый параметр является C-строкой:

int printf( const char* ... );

Это гарантирует, что при любом вызове printf() ей будет передан первый аргумент типа const char*. Содержание такой строки, называемой форматной, определяет, необходимы ли дополнительные аргументы при вызове. При наличии в строке формата метасимволов, начинающихся с символа %, функция ждет присутствия этих аргументов. Например, вызов



printf( "hello, world\n" );

имеет один строковый аргумент. Но

printf( "hello, %s\n", userName );

имеет два аргумента. Символ %

говорит о наличии второго аргумента, а буква s, следующая за ним, определяет его тип – в данном случае символьную строку.

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

Отметим, что следующие объявления неэквивалентны:

void f();

void f( ... );

В первом случае f()

объявлена как функция без параметров, во втором – как имеющая ноль или более параметров. Вызовы

f( someValue );

f( cnt, a, b, с );

корректны только для второго объявления. Вызов

f();

применим к любой из двух функций.

Упражнение 7.4


Какие из следующих объявлений содержат ошибки? Объясните.



(a) void print( int arr[][], int size );

(b) int ff( int a, int b = 0, int с = 0 );
(c) void operate( int *matrix[] );



(d)        char   *screenInit( int height = 24, int width,       

                        char  background );

(e)        void   putValues( int (&ia)[] );

Упражнение 7.5

Повторные объявления всех приведенных ниже функций содержат ошибки. Найдите их.



(a) char *screenInit( int height, int width,

                        char background = ' ' );

    char *screenInit( int height = 24, int width,

                        char background );

(b) void print( int (*arr)[6], int size );

    void print( int (*arr)[5], int size );

(c) void manip( int *pi, int first, int end = 0 );
    void manip( int *pi, int first = 0, int end = 0 );

Упражнение 7.6

Даны объявления функций.



void print( int arr[][5], int size );

void operate(int *matrix[7]);

char *screenInit( int height = 24, int width = 80,
                  char background = ' ' );

Вызовы этих функций содержат ошибки. Найдите их и объясните.



(a) screenInit();

(b) int *matrix[5];

    operate( matrix );

(c) int arr[5][5];
    print( arr, 5 );

Упражнение 7.7

Перепишите функцию putValues( vector<int> ), приведенную в подразделе 7.3.4, так, чтобы она работала с контейнером list<string>. Печатайте по одному значению на строке. Вот пример вывода для списка из двух строк:

( 2 )



"first string"

"second string"



Напишите функцию main(), вызывающую новый вариант putValues() со следующим списком строк:



"put function declarations in header files"

"use abstract container types instead of built-in arrays"

"declare class parameters as references"

"use reference to const types for invariant parameters"
"use less than eight parameters"

Упражнение 7.8

В каком случае вы применили бы параметр-указатель? А в каком – параметр-ссылку? Опишите достоинства и недостатки каждого способа.


Содержание раздела