Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lek_1_slaydy.doc
Скачиваний:
1
Добавлен:
17.11.2019
Размер:
417.79 Кб
Скачать

Int (*matrix)[20];

Оно определяет matrix, как указатель на массив из 20 целых. Вы должны заключить в круглые скобки (*matrix), поскольку квадратные скобки массива имеют больший приоритет, чем символ указателя *. Целых значений еще даже не существует; все что вы сделали — только дали указание компилятору, что matrix — указатель на массив определенного размера.

Чтобы выделить память для матрицы размером 10x20 и присво­ить ее адрес переменной matrix,надо:

matrix = new int[10][20];

Оператор new выделяет память для массива. Адрес, получившийся в результате, присваивается matrix. Для создания куба 8x8x8 следует написать следующее:

Int (*matrix)[8][8];

matrix = new int[8][8][8];

Такое объявление matrix определяет вторую и третью размерность массива, указывая компилятору, что matrix адресует массив целых значений размерностью 8x8. Выражение new определяет все три измерения, вы­деляя пространство для указанного числа массивов 8x8, другими словами — трехмерного куба.

При вьщелении пространства для многомерного массива первый индекс может быть переменной, а второй и последующие должны быть константами. Например, если целая переменная v равна 40, то следующие строки

int (*matrix)[20];

matrix = new int[v][20];

выделяют пространство для двухмерного массива размерностью 40x20 элементов целых значений, адресуемого matrix.

Удаление многомерных массивов любой размерности происходит так, как будто они имеют лишь одно измерение:

delete[] matrix;

Перегрузка функций

Пример: программа, которая должна рисовать не­сколько различных фигур. Каждая функция прорисовки имеет свое собственное имя, что делает код "усыпан­ным" функциями типа DrawEllipse, DrawCircle, DrawSquare, DrawLine и т.д мы получим программу, словно написанную заикой:

DrawEllipse(ellipse); DrawCircle(circle); DrawSquare(square); DrawLine(line);

Не будет ли лучше, если вы используете одно и то же имя функции (назовем ее Draw) для вывода всех фигур?

Draw(ellipse); Draw(circle); Draw(square); Draw(line);

В С++ многочисленные функции могут иметь одинаковое имя до тех пор, пока они отличаются хотя бы одним параметром. Функции "перегружены", поскольку их имена одинаковы, а выполняемая ими работа — различна.

Многие функции Draw в нашей гипотетической графической программе остаются раздельными и различными, и написаны точно так же, как и другие не перегруженные функции. Но компилятор С++ распознает их по тому, как они используются, а не только по их именам.

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

Листинг 1.13. OVERLOAD.CPP (перегрузка функций)

1 :#include <iostream.h>

2:

3:int square(int а);

4:double square(double а);

5:long double square(long double a);

6:

7:main()

8:{

9: int x = 10;

10 double у = 20.5;

11 long double z = 30.75;

12:

13: cout << square(x) << '\n';

14: cout << square(y) << '\n';

15: cout << square(z) << '\n';

16: return 0;

17: } 18:

19:int square(int а)

20:{

21: return а * а;

22: } 23:

24:double square(double а)

25:{

26: return а * а;

27: } 28:

29:long double square(long double a)

30:{

31: return а * а;

32: }

Прототипы трех перегруженных функции square() определены в строках 3-5. Все функции имеют одина­ковое имя, но, тем не менее, они различны, поскольку каждая из них отличается хотя бы одним параметром от другой. Сами функции реализованы в строках 19-32 как раздельные, т.е. имеющие различные имена.

В строках 13-15 показано, как перегруженные функции могут прояснять суть программы. Несмотря на различия в типах данных, очевидно, что каждый оператор выводит квадрат аргумента. Это куда более прият­но, чем различать функции по именам типа squareInt(), squareDouble() и squareLongDouble(). Конечно, ре­шать, стоит ли перегружать функции, которые выполняют более или менее схожую работу, придется вам. Ес­ли вы назовете все функции в вашей программе одним и тем же именем (с учетом того, что они должны от­личаться хотя бы одним своим аргументом), то ваш код может стать совершенно непостижимым, как новелла, представляющая собой многократное повторение одного и того же слова.

Аргументы функций по умолчанию

Важное свойство С++ — возможность передачи аргумента в функцию по умолчанию.

Оно используется, если при вызове функции необходима только часть параметров, а не все.

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

int sum(int a, int b, int с, int d)

{return a + b + с + d;}

Для вызова функции только с двумя аргументами (назовем их vl и v2) следует дополнить нулями два не­достающих параметра:

cout <<sum(v1, v2, 0, 0);

Это ограничение невелико, но оно заставляет вас разбираться в документации по функции sum() для того, чтобы определить, какими значениями дополнить неиспользуемые параметры.

Ошибочное употребление -1 или другого значения вместо параметров с и d, что вполне может допустить невнимательный программист, за­ставит функцию вернуть неправильную сумму.

Аргументы функций по умолчанию дополняют необходимые значения для незаданных аргументов. Для объявления значения аргумента по умолчанию в прототипе функ­ции завершите параметр функции знаком равенства и необходимым значением:

int sum(int a, int b, int с = 0, int d = 0);

Подобное объявление sum() позволяет вызывать ее не только с двумя, но и с большим числом аргументов -до четырех.

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

Теперь допустимы следующие операторы:

cout << sum(1, 2); // а == 1, b == 2, с == 0, d == 0

cout << sum(1, 2, 3); // а == 1, b == 2, с == 3, d == 0

cout << sum(1, 2, 3, 4); // а == 1, b == 2, с == 3, d == 4

Листинг 1.14 показывает более реальньй пример функции с аргументами по умолчанию. Программа центри­рует введенную строку путем ее копирования в строковый буфер вывода, обрамленной одним или двумя симво­лами заполнения. Можно использовать функцию Center() программы-примера для подготовки строк вида:

- ***♦ Error: You goofed big time! **** <««« Press any key to continue »>>>>>

Скомпилируйте CENTER.CPP из листинга 12.14 как EasyWin- или DOS-приложение. Запустите програм­му и введите строку, выводящуюся несколькими способами функцией Center(), которая заодно демонстрирует использование аргументов по умолчанию.

Листинг 1.14. CENTER.CPP (использование аргументов функции по умолчанию)

1 : #include <iostream.h>

2: #include <string.h>

3:

4: #define SIZE 128

5:

6: void Center(const char *instr, char *outstr,

7: int width = 0, char lFill = "-', char rFill = '-');

8:

9: main()

10: {

11: char instr[SIZE]; // Вводимая строка

12: char outstr[SIZE]; // Выводимая строка

13: int length; // Длина строки в символах 14:

15: cout « "Enter a string:";

16: cin.getline(instr, SIZE / 2);

17: length = strlen(instr); 18:

19: Center(instr, outstr);

20: cout « outstr « '\n";

21: Center(instr, outstr, length + 8);

22: cout « outstr « "\ri';

23: Center(instr, outstr, length + 16, '*', '*');

24: cout « outstr « '\rf;

25: Center(instr, outstr, 78, '<", >);

26: cout « outstr « "\n"; 27:

28: return 0;

29: } 30:

31: // instr: Указатель на входную строку

32: //outstr: Указатель на выходную строку

33: // width: Окончательная желаемая длина выходной строки

34: // fill: Символ для заполнения выходной строки 35:

36: void Center(const char *instr, char *outstr,

37: int width, char lFill, char rFill)

38: {

39: if (outstr == 0) // Выходная строка не должна быть нулевой

40: return; // Если нулевая - немедленное возвращение 41:

42: if (instr == 0) { // Если входная строка нулевая,

43: *outstr = 0; // Выводим пустую строку

44: return; // и возвращаемся.

45: } 46:

47: // Вычисление переменных для заполнения выходной строки

48: int len = strlen(instr);

49: if (width < len)

50: width = len;

51: int wd2 = (width - len) / 2;

52:

53: int i; // Индекс строки и управляющая переменная для цикла for

54:

55: for (i = 0; i < wd2; i++)

56: outstr[i] = lFill;

57: for (/*i = i*/; i < wd2 + len; i++)

58: outstr[i] = instr[i - wd2];

59: for (/*i = i*/; i < width; i++)

60: outstr[i] = rFill;

61: outstr[i] = 0; // Завершаем строку нулем

62: }

В программе объявляется прототип функции Center() с тремя аргументами по умолчанию:

void Center(const char *instr, char *outstr, int width = 0, char lFill = '-', char rFill = '-');

Первые два параметра — адреса входной и выходной строки. Входная строка объявлена с ключевым сло­вом const для предохранения ее от изменения в теле функции. Последние три параметра определены со значениями по умолчанию, которые будут их инициализировать при пропуске соответствующих аргументов в операторе, в котором вызывается функция Center(). Как показано в программе, первый вызов функции дол­жен быть только с двумя аргументами:

Center(instr, outstr);

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

Ссылки

int i = 1234;

int *p = &i;

объявляется целая переменная i, инициализированная значением 1234, и указатель на целое p, адресующий i.

В соответствии с этими объявлениями следующие два оператора выводят значение i:

cout << "i == " << i << '\n' ;

cout <<"i == " << *p <<'\n';

Выражение *p указывает компилятору, что следует использовать значение, адресуемое р.

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

С++ предлагает альтернативу для более безопасного доступа к переменным через указатели. Объявив ссы­лочную переменную, вы создадите объект, который, как указатель, ссылается на другое значение, но, в от­личие от указателя, постоянно привязан к своему alter ego ("второму я"). Ссылка на значение всегда ссылает­ся на это значение.

Ссылки, в основном, используются в качестве переменных, параметров функций и результатов функций.

Ссылки в качестве переменных

В программе (листинг 1.15) приводятся четыре способа адреса­ции и вывода целого значения.

Листинг 1.15. REFVAR.CPP (демонстрация ссылочных переменных)

1:#include <iostream.h>

2:

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]