Форвард объявить структуру в Objective-C - PullRequest
14 голосов
/ 03 февраля 2012

Я создаю протокол, и одним из параметров метода, который я определяю, является CMTime*. Я хотел бы переслать объявить CMTime, а не включать его. Тем не менее, я попробовал @class CMTime, и он жалуется, что он переопределен в другом месте как символ другого типа. Документация говорит, что это структура. Я пытался вперед, объявив его как

struct CMTime;

но он все еще жалуется, что не знает, что это такое.

Есть идеи, что я делаю не так?

Ответы [ 3 ]

18 голосов
/ 03 февраля 2012

Источник, скомпилированный как ObjC, имеет те же правила, что и C в этом отношении.

В этом отношении источник, скомпилированный как ObjC ++, имеет те же правила, что и C ++.

@class MONClass; - это предварительное объявление типа ObjC. Не используйте его для структур.

struct t_mon_struct; является предварительным объявлением структуры с именем C или C ++ struct. Не используйте его для типов ObjC. Технически, компилятор позволяет вам также объявить класс C ++ как структуру (при условии, конечно, что класс также объявлен в глобальном пространстве имен).

Таким образом, корень семантики все сводится к C (при условии, что это перевод ObjC). Я перестану упоминать ObjC и C ++.

Здесь есть несколько общих источников сложности:

  • Пространство имен структуры
  • объявление структуры
  • избегая нескольких определений меток

struct t_mon_struct; является предварительным объявлением теговой структуры. В частности, это то, чье имя существует в пространстве имен struct.

теговая структура, которая существует в пространстве имен struct:

struct t_mon_struct { int a; };

анонимная структура с typedef в глобальном пространстве имен:

typedef struct { int a; } t_mon_struct;

теговая структура с typedef в глобальном пространстве имен:

typedef struct t_mon_struct { int a; } t_mon_struct;

CMTime объявляется следующим образом:

typedef struct
{
    CMTimeValue    value;
    CMTimeScale    timescale;
    CMTimeFlags    flags;
    CMTimeEpoch    epoch;
} CMTime;

В частности, глобальная метка typedef CMTime связана с анонимной структурой в пространстве имен struct и на нее нельзя ссылаться, если ее объявление не видно.

Если бы CMTime было объявлено:

typedef struct CMTime
{
    CMTimeValue    value;
    CMTimeScale    timescale;
    CMTimeFlags    flags;
    CMTimeEpoch    epoch;
} CMTime;

тогда вы могли бы получить, используя предварительную декларацию struct CMTime:

struct CMTime;
void foo(struct CMTime*);

Так как он не был объявлен таким образом, вам нужно #include объявить его или разработать обходной путь.

Сложности ухудшаются, когда typedef структуры отличается от ее тега. Вы не можете связать или переопределить typedef (в C). Однако вы можете обойти его, используя имя в пространстве имен struct - которое некоторые авторы библиотеки считают закрытым.

1 голос
/ 11 марта 2015

Просто добавив typedef до того, как структура поможет мне.

typedef struct CMTime;
0 голосов
/ 03 февраля 2012

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

...