Начальное событие заставки Mac

Объявление функции C

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

int putchar(int);

Это позволяет вам написать такой код.

int puts(const char *);
int main() {
    puts("Hello, world!");
}

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

#include <stdio.h>

int eighty_four() {
    return 84;
}

int output_result(int callback()) {
    printf("Returned: %d\n", callback());
    return 0;
}

int main() {
    return output_result(eighty_four);
}

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

int output_result(int());

Один аргумент в конструкторе

Не знаете вон тот? Ну, позвольте мне напомнить.

A a(B());

Да, это точно такое же объявление функции. A - int, a - output_result, а B - int.

Вы можете легко заметить конфликт C с новыми функциями C ++. Точнее, конструкторы - это имя класса и скобки, а синтаксис альтернативного объявления с () вместо =. По дизайну C ++ пытается быть совместимым с C-кодом, и поэтому он должен иметь дело с этим случаем - даже если практически никто не заботится. Поэтому старые функции C имеют приоритет над новыми функциями C ++. Грамматика деклараций пытается совместить имя как функцию, прежде чем возвращаться к новому синтаксису с помощью (), если он терпит неудачу.

Если одна из этих функций не существовала или имела другой синтаксис (например, {} в C ++ 11), эта проблема никогда бы не произошла для синтаксиса с одним аргументом.

Теперь вы можете спросить, почему работает A a((B())). Ну, давайте объявим output_result бесполезными круглыми скобками.

int output_result((int()));

Это не сработает. Грамматика требует, чтобы переменная не была в круглых скобках.

<stdin>:1:19: error: expected declaration specifiers or ‘...’ before ‘(’ token

Однако C ++ ожидает стандартное выражение здесь. В C ++ вы можете написать следующий код.

int value = int();

И следующий код.

int value = ((((int()))));

C ++ ожидает выражения внутри внутри круглых скобок ... хорошо ... выражение, в отличие от типа C. Круглые скобки ничего здесь не означают. Однако, вставляя бесполезные круглые скобки, объявление функции C не сопоставляется, и новый синтаксис может быть соответствующим образом сопоставлен (который просто ожидает выражение, например 2 + 2).

Дополнительные аргументы в конструкторе

Конечно, один аргумент хорош, но как насчет двух? Дело не в том, что у конструкторов может быть только один аргумент. Один из встроенных классов, который принимает два аргумента, - std::string

std::string hundred_dots(100, '.');

. Все это хорошо и прекрасно (технически, он имел бы самый неприятный синтаксический анализ, если бы он был записан как std::string wat(int(), char()), но давайте будем честными - кто бы это написал? Но давайте предположим, что этот код имеет неприятную проблему. Предположим, что вам нужно все положить в круглые скобки.

std::string hundred_dots((100, '.'));

Не совсем так.

<stdin>:2:36: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
In file included from /usr/include/c++/4.8/string:53:0,
                 from <stdin>:1:
/usr/include/c++/4.8/bits/basic_string.tcc:212:5: error:   initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ [-fpermissive]
     basic_string<_CharT, _Traits, _Alloc>::
     ^

Я не уверен, почему g ++ пытается преобразовать char в const char *. В любом случае конструктор вызывался только с одним значением типа char. Нет перегрузки, которая имеет один аргумент типа char, поэтому компилятор запутан. Вы можете спросить - почему аргумент имеет тип char?

(100, '.')

Да, , здесь - запятый оператор. Оператор запятой принимает два аргумента, и дает аргумент правой стороны. Это не очень полезно, но это то, что нужно знать для моего объяснения.

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

std::string hundred_dots((100), ('.'));

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

Нулевые аргументы в конструкторе

Возможно, вы заметили функцию eighty_four в моем объяснении.

int eighty_four();

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

int eighty_four(());

Почему это так? Ну, () не является выражением. В C ++ вы должны поставить выражение между круглыми скобками. Вы не можете писать auto value = () в C ++, потому что () ничего не значит (и даже если бы это было так, как пустой кортеж (см. Python), это был бы один аргумент, а не ноль). Практически это означает, что вы не можете использовать сокращенный синтаксис без использования синтаксиса {} C ++ 11, так как в круглых скобках нет выражений, а C-грамматика для деклараций функций всегда будет применяться.

13
задан tig 15 September 2009 в 11:14
поделиться

2 ответа

Наконец нашел - решение состоит в том, чтобы использовать NSDistributedNotificationCenter и наблюдать следующие события

  • com.apple.screensaver.didstart
  • com.apple.screensaver.willstop
  • com.apple .screensaver.didstop
  • com.apple.screenIsLocked
  • com.apple.screenIsUnlocked

Like

[[NSDistributedNotificationCenter defaultCenter]
   addObserver:self
   selector:@selector(screensaverStarted:)
   name:@"com.apple.screensaver.didstart"
   object:nil];
31
ответ дан 1 December 2019 в 19:40
поделиться

While there is no Carbon event for this, you can get notified when the current application changes, and then check to see if the new application is the screen saver process.


// Register the event handler for when applications change
{
    EventTypeSpec es;
    es.eventClass = kEventClassApplication;
    es.eventKind = kEventAppFrontSwitched;
    InstallApplicationEventHandler(&appChanged, 1, &es, NULL, NULL);
}

OSStatus appChanged(EventHandlerCallRef nextHandler, EventRef anEvent, void* userData)
{
    ProcessSerialNumber psn;    
    GetEventParameter(anEvent, kEventParamProcessID, typeProcessSerialNumber,
                      NULL, sizeof(psn), NULL, &psn);

    // Determine process name
    char procName[255];
    {
        ProcessInfoRec pInfo;
        Str255 procName255;
        FSRef ref;

        pInfo.processInfoLength = sizeof(ProcessInfoRec);
        pInfo.processName = procName255;
        pInfo.processAppRef = &ref;
        GetProcessInformation(&psn, &pInfo);

        const unsigned int size = (unsigned int)procName255[0];
        memcpy(procName, procName255 + 1, size);
        procName[size] = '\0';
    }

    if(strcmp(procName, "ScreenSaverEngine") == 0)
    {
        NSLog(@"Found %s\n", procName);
    }

    return noErr;
}
2
ответ дан 1 December 2019 в 19:40
поделиться
Другие вопросы по тегам:

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