Преимущества Использования указателей функции

instanceof - это нечто особенное, связанное с наследованием типов и . Ознакомьтесь с документацией по Java .

В вашем случае вы хотите сравнить строку temp со строкой "BiologyLab". Просто используйте

if ("BiologyLab".equals(temp)) { 
    ...
}

и посмотрите Как сравнивать строки в Java для получения дополнительной информации.

14
задан Brock Woolf 24 March 2009 в 03:40
поделиться

10 ответов

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

Указатели функции не имеют никакого отношения к производительности и никогда не должны использоваться для получения производительности.

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

Простым примером является универсальная функция сортировки. Это должно иметь некоторый способ сравнить два элемента, чтобы определить, как они должны быть отсортированы. Это могло быть указателем функции, переданным функции вида и на самом деле станд. C++:: вид () может использоваться точно как этот. Если Вы спрашиваете это к последовательностям вида типа, который не определяет меньше, чем оператор, необходимо передать в указателе функции, который это может назвать для выполнения сравнения.

И это приводит нас приятно к превосходящей альтернативе. В C++ Вы не ограничены указателями функции. Вы часто используете функторы вместо этого - то есть, классы, которые перегружают оператор (), так, чтобы их можно было "назвать", как будто они были функциями. Функторы имеют несколько больших преимуществ перед указателями функции:

  • Они предлагают больше гибкости: они - законченные классы, с конструктором, деструктором и членскими переменными. Они могут поддержать состояние, и они могут выставить другие функции членства, которые может назвать окружающий код.
  • Они быстрее: в отличие от указателей функции, тип которых только кодирует подпись функции (переменная типа void (*)(int) может быть любая функция, которая берет интервал и возвращается пусто. Мы не можем знать, какой), тип функтора кодирует точную функцию, которая должна быть вызвана (Так как функтор является классом, назовите это C, мы знаем, что функция для вызова и всегда будет, C:: оператор ()). И это означает, что компилятор может встроить вызов функции. Это - волшебство, которое делает универсальный станд.:: вид настолько же быстро как Ваша кодированная рукой функция сортировки, специально разработанная для Вашего типа данных. Компилятор может устранить все издержки вызывания пользовательской функции.
  • Они более безопасны: в указателе функции существует очень мало безопасности типов. У Вас нет гарантии, что это указывает на допустимую функцию. Это могло быть ПУСТЫМ. И большинство проблем с указателями относится к указателям функции также. Они опасны и подвержены ошибкам.

Указатели функции (в C) или функторы (в C++) или делегаты (в C#) все решают ту же проблему с разными уровнями элегантности и гибкости: Они позволяют Вам рассматривать функции так первоклассные значения, раздавая их, как Вы были бы любая другая переменная. Можно передать функцию другой функции, и она вызовет функцию в требуемое время (когда таймер истечет, когда окно нуждается в перерисовке, или когда она должна сравнить два элемента в массиве),

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

Таким образом, это - то, где Вы используете указатели функции: Когда более сложные альтернативы не доступны (т.е. Вы застреваете в C), и необходимо передать одну функцию другому. Наиболее распространенный сценарий является обратным вызовом. Вы определяете функцию F, что Вы хотите, чтобы система звонила, когда X происходит. Таким образом, Вы создаете указатель функции, указывающий F и передачу это к рассматриваемой системе.

Таким образом, действительно забудьте о John Carmack и не предполагайте, что что-либо Вы видит в его коде, волшебно сделает Ваш код лучше, если Вы скопируете его. Он использовал указатели функции, потому что игры, которые Вы упоминаете, были записаны в C, где превосходящие альтернативы не доступны, и не потому что они - некоторый волшебный компонент, простое существование которого делает код выполненным быстрее.

24
ответ дан 1 December 2019 в 05:55
поделиться

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

int MyFunc()
{
  if(SomeFunctionalityCheck())
  {
    ...
  }
  else
  {
    ...
  }
}

Если эта функция вызвана глубоко в важных циклах затем, вероятно, лучше для использования указателя функции для MyFunc:

int (*MyFunc)() = MyFunc_Default;

int MyFunc_SomeFunctionality()
{
  // if(SomeFunctionalityCheck())
  ..
}

int MyFunc_Default()
{
  // else
  ...
}

int MyFuncInit()
{
  if(SomeFunctionalityCheck()) MyFunc = MyFunc_SomeFunctionality;
}

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

Выполнить Intel совместимый код байта Windows, который мог бы быть полезен для интерпретатора. Например, вот является функция stdcall возвратом 42 (0x2A), сохраненный в массиве, который может быть выполнен:

code = static_cast<unsigned char*>(VirtualAlloc(0, 6, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE));
// mov eax, 42
code[0] = 0x8b;
code[1] = 0x2a;
code[2] = 0x00;
code[3] = 0x00;
code[4] = 0x00;
// ret
code[5] = 0xc3;
// this line executes the code in the byte array
reinterpret_cast<unsigned int (_stdcall *)()>(code)();

...

VirtualFree(code, 6, MEM_RELEASE);

);

9
ответ дан 1 December 2019 в 05:55
поделиться

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

И не, они не о скорости. Указатели функции об удобстве.

Jonathan

6
ответ дан 1 December 2019 в 05:55
поделиться

В эти дни, каковы лучшие и наиболее практические применения целых чисел на современных языках c-стиля?

5
ответ дан 1 December 2019 в 05:55
поделиться

Просто разговор о C#, но указатели функции используется на всем протяжении C#. Делегаты и События (и Лямбды, и т.д.) являются всеми указателями функции под капотом, таким образом, почти любой проект C# будет пронизанным указателями функции. В основном каждый обработчик событий, около каждого запроса LINQ, и т.д. - будет использовать указатели функции.

3
ответ дан 1 December 2019 в 05:55
поделиться

В тусклое, средневековье перед C++ был общий шаблон, который я использовал в своем коде, который должен был определить структуру с рядом указателей функции, которые (обычно) воздействовали на ту структуру в некотором роде и обеспечили особые поведения для нее. В терминах C++ я просто создавал vtable. Различие было то, что я мог побочный эффект структура во времени выполнения для изменения поведений отдельных объектов на лету по мере необходимости. Это предлагает намного более богатую модель наследования за счет устойчивости и простоты отладки. Самая большая стоимость, однако, была то, что был точно один человек, который мог написать этот код эффективно: я.

Я использовал это в большой степени в платформе UI, которые позволяют мне изменить способ, которым были нарисованы объекты, кто был целью команд, и так далее, на лету - что-то, что предложили очень немного UIs.

Формализация этого процесса на языках OO лучше каждым значимым способом.

4
ответ дан 1 December 2019 в 05:55
поделиться

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

Тем не менее я обеспечу кавычку, которую я получил от бывшего моего преподавателя:

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

5
ответ дан 1 December 2019 в 05:55
поделиться

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

3
ответ дан 1 December 2019 в 05:55
поделиться

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

Без закрытий и легкого синтаксиса, они - вид общего количества. Таким образом, Вы склонны использовать их намного менее, чем желаемый. Главным образом для функций "обратного вызова".

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

C# имеет закрытия, таким образом, указатели функции (которые на самом деле хранят объект, таким образом, это не просто необработанная функция, но и введенное состояние также) значительно более применимы там.

Отредактируйте Один из комментариев, сказал, что должна быть демонстрация функций высшего порядка с указателями функции. Любая функция, берущая функцию обратного вызова, является функцией высшего порядка. Как, скажем, EnumWindows:

BOOL EnumWindows(          
    WNDENUMPROC lpEnumFunc,
    LPARAM lParam
);

Первый параметр является функцией для передачи в, достаточно легкий. Но с тех пор нет никаких закрытий в C, мы получаем этот прекрасный второй параметр: "Указывает определенное приложением значение, которое будет передано функции обратного вызова". То определенное приложением значение позволяет Вам вручную раздавать невведенное состояние для компенсации из-за отсутствия закрытий.

Платформа.NET также заполнена подобными проектами. Например, IAsyncResult. AsyncState: "Получает пользовательский объект, который квалифицирует или содержит информацию об асинхронной операции". Так как IAR - все, что Вы входите в свой обратный вызов без закрытий, Вам нужен способ пихнуть некоторые данные в асинхронный op, таким образом, можно выбросить его позже.

3
ответ дан 1 December 2019 в 05:55
поделиться

Указатели функции быстры

В какой контекст? По сравнению с?

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

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

1
ответ дан 1 December 2019 в 05:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: