Школа создателей компьютерных игр

BannerDrive.ru
[Главная] [С чего начать?] [Дистанционное обучение] [Статьи] [Обучалки] [Книги] [Софт] [Форум] [Ссылки] [О сайте]

Указатели на функции



Подпишитесь на рассылку "Создание компьютерных игр"

Рассылки Subscribe.Ru
Создание компьютерных игр

Рассылка выходит раз в месяц.


Понравился сайт? Узнайте, как помочь сайту.


Рекомендуемые книги


Андре Ламот.
Программирование трехмерных игр для Windows. Советы профессионала по трехмерной графике и растеризации


Андре Ламот.
Программирование игр для Windows. Советы профессионала


Проголосуйте за сайт в рейтинге GameTop!
(нажмите на кнопку рейтинга)

GameTop - рейтинг игровых ресурсов. Портал Rolemancer (www.rolemancer.ru)

Не забывайте, что результаты рейтинга обновляются раз в неделю. Пожалуйста, голосуйте почаще!


Статистика посещаемости

Rambler's Top100

Указатели на указатели | Все обучалки раздела | QSort

Описание

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

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

Скачать обучалку (Visual C++ 6)

Работа программы

Исходный код

// Done by TheTutor -- 10/8/01
// Перевод © 2005 Евгений Казеко
// www.gamecoder.kazeko.com
// evgeniy@kazeko.com

/*  
      Этот "урок" посвящен указателям на функции -- Подразумевается, что вы знаете,
      что такое указатель и представляете в общих чертах, как работают указатели.

      Итак, мы напишем функцию "printName", параметром которой и будет указатель
      на функцию. Это позволит нам добиться от "printName" возможности печати имени
      одним из нескольких желаемых способов.

      Вдобавок, мы напишем еще две функции:
      horzPrint() -- Печатает имя по горизонтали
      vertPrint() -- Печатает имя по вертикали

      Пока что все просто, верно? Если вы слегка запутались, не беспокойтесь, 
      все станет понятным :)
      
*/


#include <stdio.h>

// Эта функция принимает char*, передаваемый как параметр, и печатает его по
// горизонтали (то есть так, как обычно печатается текст)
void horzPrint(char*);

void vertPrint(char*); // Эта функция принимает char*, передаваемый как параметр, и печатает его
                                 // по вертикали -- Если передать "game", то слово напечатается вот так:
                                 // g
                                 // a
                                 // m
                                 // e


// Вот здесь и происходит все "волшебство"

// Первый параметр (char*) это имя, которое будет напечатано

// А это что еще за мешанина -- void (*print)(char*) ???
// Это как раз то место, про которое мы говорим, что функция принимает указатель на функцию.

// "void" это возвращаемый тип указателя на функцию (обратите внимание, что horzPrint()
// и vertPrint() обе возвращают void)

// (*print) это "имя" указателя на функцию. Что здесь важно, это '*' 
// перед "print" -- '*' означает, что это указатель на функцию.
// Мы могли бы назвать функцию "spitOutToScreen", если бы захотели 
// (т.е. заменить "print" на "spitOutToScreen")

// И наконец, "char*" это то, что наша "функция" принимает в качестве параметра (параметров)
// Это очень похоже на "нормальное" объявление функции.
// Еще раз, обратите внимание что horzPrint() и vertPrint() принимают char* и ТОЛЬКО char*
// в качестве входных параметров.

void printName(char*, void (*print)(char*));


int main()
{
      char name[] = "TheTutor"; // Это имя -- классное имя, по мнению автора обучалки :)

      // Сперва напечатаем его вертикально
      printName(name,vertPrint);

      // А теперь напечатаем его горизонтально
      printName(name,horzPrint);

            return 0; // И все -- программа завершена

}


// Эта функция принимает "имя" ("name") и печатает его горизонтально (т.е. просто 
// печатает его на экран)
void horzPrint(char *name)
{
      // Проверка на ошибку -- Убедимся, что мы получили существующий указатель
      if(!name)
            return;

      printf("%s",name); // Просто печатаем имя

}


// Эта функция принимает "имя" ("name") и печатает его вертикально 
// (т.е. печатает каждую букву на новой строке)
void vertPrint(char *name)
{
      int index = 0; // Это индекс печатаемой буквы в "name" 

      // Проверка на ошибку -- Убедимся, что мы получили существующий указатель
      if(!name)
            return;

      // Пока мы НЕ достигли конца "name"
      while(name[index] != '\0')
      {
            printf("%c",name[index++]); // Печатаем "текущую букву" имени
                                                  // и увеличиваем index на 1 ПОСЛЕ того, как
                                                    // буква напечатана
            printf("\n"); // Переходим на следующую строку
      }

}

// Эта функция принимает печатаемое имя "name" и указатель на функцию, который
// указывает на функцию, реализующую способ, которым следует печатать "name".
void printName(char *name, void (*print)(char*))
{
      print(name); // Печатаем имя (оно будет напечатано тем стилем, который
                         // определен указателем функции).

      printf("\n"); // После этого напечатаем "переход строки"
}

/*

  Давайте повторим:
  
  Надеюсь, очевидно то, что синтаксис указателей на функции ОЧЕНЬ ПОХОЖ
  на "нормальные объявления функции" -- Рассмотрим функцию еще раз:

  void printName(char*, void (*print)(char*));
      |
      |__ Тип, возвращаемый функцией printName() (т.е. нет возвращаемого типа)


  void printName(char*, void (*print)(char*));
                  |
                  |__ Имя функции (как и для любой объявляемой вами функции, вы выбираете его)


  void printName(char*, void (*print)(char*));
                              |
                              |__ Первый "входной параметр" функции, она принимает char* (массив char)


  void printName(char*, void (*print)(char*));
                                                |
                                                |__ Эта мешанина "void (*print)(char*)" определяет
                                                      второй входной параметр printName(), которым
                                                      является указатель на функцию


  /////////////////// А теперь рассмотрим подробно указатель на функцию

  void (*print)(char*)
      |
      |__ Возвращаемый тип указателя на функцию (т.е. нет возвращаемого типа)


  void (*print)(char*)
              |
              |__ Имя указателя на функцию.  Здесь важен символ '*'. Этот символ
                    говорит компилятору, что "это указатель на функцию" -- Имя "print"
                    мы выбираем, как и для любой другой "функции".

  void (*print)(char*)
                          |
                          |__ Это первый (и единственный) параметр, передаваемый указателю
                                на функцию. Им является char* (массив char)

  

  Надеюсь, что эта обучалка прояснила запутанный синтакс того, что программисты
  называют "указатели на функции".

*/

// Перевод © 2005 Евгений Казеко
// www.gamecoder.kazeko.com
// evgeniy@kazeko.com

Скачать обучалку (Visual C++ 6)

Указатели на указатели | Все обучалки раздела | QSort

[Главная] [С чего начать?] [Дистанционное обучение] [Статьи] [Обучалки] [Книги] [Софт] [Форум] [Ссылки] [О сайте]

Copyright © 2003-2005 Евгений Казеко. Все права защищены. E-mail: evgeniy@kazeko.com

палатки пенка; автомобильные диски найти.; Перевозки различных грузов, http://www.exmoto.com/ индивидуальный подход.; уборка помещений