Читаем Освой самостоятельно С++ за 21 день. полностью

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

long(*pFuncOne) (int,int);

long SomeFunction (int,int);

pFuncOne = SomeFunction;

pFuncOne (5,7);

Зачем нужны указатели на функции

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

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

Листинг 14.6. Видоизмененный вариант листинга 14.5 без использования указателей на функции

1: // Листинг 14.6. Видоизмененный вариант листинга 14.5 без использования

2: // указателей на функции

3: #include

4:

5: void Square (int&,int&);

6: void Cube (int&, int&);

7: void Swap (int&, int &);

8: void GetVals(int&, int&);

9: void PrintVals(int, int);

10:

11: int main

12: {

13:    bool fQuit = false;

14:    int valOne=1, valTwo=2;

15:    int choice;

16:    while (fQuit == false)

17:    {   

18:       cout << << "(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap";

19:       cin >> choice;

20:       switch (choice)

21:       {

22:          case 1:

23:             PrintVals(valOne, valTwo);

24:             GetVals(valOne, valTwo);

25:             PrintVals(valOne, valTwo);

26:             break;

27:

28:          case 2:

29:             PrintVals(valOne, valTwo);

20:             Square(valOne,valTwo);

31:             PrintVals(valOne, valTwo);

32:             break;

33:

34:          case 3:

35:             PrintVals(valOne, valTwo);

36:             Cube(valOne, valTwo);

37:             PrintVals(valOne, valTwo);

38:             break;

39:

40:          case 4:

41:             PrintVals(valOne, valTwo);

42:             Swap(valOne, valTwo);

43:             PrintVals(valOne, valTwo);

44:             break;

45:

46:          default:

47:             fOuit = true;

48:             break;

49:       }

50:

51:       if (fQuit)

52:          break;

53:    }

54:    return 0;

55: }

56:

57: void PrintVals(int x, int y)

58: {

59:    cout << "x: " << x << " y: " << y << endl;

60: }

61:

62: void Square (int & rX, int & rY)

63: {

64:    rX *= rX;

65:    rY *= rY;

66: }

67:

68: void Cube (int & rX, int & rY)

69: {

70:    int tmp;

71:

72:    tmp = rX;

73:    rX *= rX;

74:    rX = rX * tmp;

75:

76:    tmp = rY;

77:    rY *= rY;

78:    rY = rY * tmp;

79: }

80:

81: void Swap(int & rX, int & rY)

82: {

83:    int temp;

84:    temp = rX;

85:    rX = rY;

86:    rY = temp;

87: }

88:

89: void GetVals (int & rValOne, int & rValTwo)

90: {

91:    cout << "New value for ValOne: ";

92:    cin >> rValOne;

93:    cout << "New value for ValTwo: ";

94:    cin >> rValTwo;

95: }


Результат:

(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 1

х. 1 у. 2

New value for ValOne: 2

New value for ValTwo: 3

(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 3

x: 2 y: 3

x: 8 y: 27

(0)Quit (1 )Change Values (2)Square (3)Cube (4)Swap: 2

x: 8 y: 27

x: 64 y: 729

(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 4

x: 64 y: 729

x: 729 y: 64

(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 0


Анализ: Функции работают так же, как и в листинге 14.5. Информация, выводимая программой на экран, также не изменилась. Но размер программы увеличился с 22 до 46 строк. Причина в том, что вызов функции PrintVals приходится повторять для каждого блока с оператором case.

Заманчивым может показаться вариант размещения функции PrintVals вверху и внизу цикла while, а не в каждом блоке с оператором case. Но тогда функция PrintVals будет вызываться даже в случае выхода из цикла, чего быть не должно.


Упрощенный вариант вызова функции

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

pFunc(x);

или

(*pFunc) (x);

Оба выражения приведут к одному и тому же результату. Хотя первое выражение ко- роче, второе придает программе больше гибкости.


Перейти на страницу:

Похожие книги

Сущность технологии СОМ. Библиотека программиста
Сущность технологии СОМ. Библиотека программиста

В этой книге СОМ исследуется с точки зрения разработчика C++. Написанная ведущим специалистом по модели компонентных объектов СОМ, она раскрывает сущность СОМ, помогая разработчикам правильно понять не только методы модели программирования СОМ, но и ее основу. Понимание мотивов создания СОМ и ее аспектов, касающихся распределенных систем, чрезвычайно важно для тех разработчиков, которые желают пойти дальше простейших приложений СОМ и стать по-настоящему эффективными СОМ-программистами. Показывая, почему СОМ для распределенных систем (Distributed СОМ) работает именно так, а не иначе, Дон Бокс дает вам возможность применять эту модель творчески и эффективно для ежедневных задач программирования.

Дональд Бокс

Программирование, программы, базы данных / Программирование / Книги по IT