Выбрать главу

(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( vectorint ), приведенную в подразделе 7.3.4, так, чтобы она работала с контейнером liststring. Печатайте по одному значению на строке. Вот пример вывода для списка из двух строк:

( 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

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

7.4. Возврат значения

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

return;

return expression;

Первая форма используется в функциях, для которых типом возвращаемого значения является void. Использовать return в таких случаях обязательно, если нужно принудительно завершить работу. (Такое применение return напоминает инструкцию break, представленную в разделе 5.8.) После конечной инструкции функции подразумевается наличие return. Например:

void d_copy( double "src, double *dst, int sz )

{

/* копируем массив "src" в "dst"

* для простоты предполагаем, что они одного размера

*/

// завершение, если хотя бы один из указателей равен 0

if ( !src || !dst )

return;

// завершение,

// если указатели адресуют один и тот же массив

if ( src == dst )

return;

// копировать нечего

if ( sz == 0 )

return;

// все еще не закончили?

// тогда самое время что-то сделать

for ( int ix = 0; ix sz; ++ix )

dst[ix] = src[ix];

// явного завершения не требуется

}

Во второй форме инструкции return указывается то значение, которое функция должна вернуть. Это значение может быть сколь угодно сложным выражением, даже содержать вызов функции. В реализации функции factorial(), которую мы рассмотрим в следующем разделе, используется return следующего вида:

return val * factorial(val-1);

В функции, не объявленная с void в качестве типа возвращаемого значения, обязательно использовать вторую форму return, иначе произойдет ошибка компиляции. Хотя компилятор не отвечает за правильность результата, он сможет гарантировать его наличие. Следующая программа не компилируется из-за двух мест, где программа завершается без возврата значения:

// определение интерфейса класса Matrix

#include "Matrix.h"

bool is_equa1( const Matrix ml, const Matrix m2 )

{

/* Если содержимое двух объектов Matrix одинаково,

* возвращаем true;

* в противном случае - false

*/

// сравним количество столбцов

if ( ml.colSize() != m2.co1Size() )

// ошибка: нет возвращаемого значения

return;

// сравним количество строк

if ( ml.rowSize() != m2.rowSize() )

// ошибка: нет возвращаемого значения

return;

// пробежимся по обеим матрицам, пока

// не найдем неравные элементы

for ( int row = 0; row ml.rowSize(); ++row )

for ( int col = 0; co1 ml.colSize(); ++co1 )

if ( ml[row][col] != m2[row][col] )

return false;

// ошибка: нет возвращаемого значения

// для случая равенства

}

Если тип возвращаемого значения не точно соответствует указанному в объявлении функции, то применяется неявное преобразование типов. Если же стандартное приведение невозможно, происходит ошибка компиляции. (Преобразования типов рассматривались в разделе 4.1.4.)