Я примерно понимаю правила с тем, что #include делает с препроцессором C, но я не понимаю это полностью. Прямо сейчас у меня есть два заголовочных файла, Move.h и Board.h что и определение типа их соответствующий тип (Перемещение и Совет). В обоих заголовочных файлах я должен сослаться на тип, определенный в другом заголовочном файле.
Прямо сейчас у меня есть #include "Move.h" в Board.h и #include "Board.h" в Move.h. Когда я компилирую, хотя, gcc зеркальные отражения и дает мне длинное (что похоже бесконечный рекурсивный), зеркальное отражение сообщения об ошибке между Move.h и Board.h.
Как я включаю эти файлы так, чтобы я рекурсивно не включал неограниченно долго?
Вам нужно посмотреть в прямые объявления , вы создали бесконечные петли включенных, передовые декларации являются правильным решением.
Вот пример:
MOVE.H
#ifndef MOVE_H_
#define MOVE_H_
struct board; /* forward declaration */
struct move {
struct board *m_board; /* note it's a pointer so the compiler doesn't
* need the full definition of struct board yet...
* make sure you set it to something!*/
};
#endif
PORD.H
#ifndef BOARD_H_
#define BOARD_H_
#include "Move.h"
struct board {
struct move m_move; /* one of the two can be a full definition */
};
#endif
MAIN.C
#include "Board.h"
int main() { ... }
Примечание: Всякий раз, когда вы создаете «доску», вам нужно будет что-то подобное ( Есть несколько способов, вот пример):
struct board *b = malloc(sizeof(struct board));
b->m_move.m_board = b; /* make the move's board point
* to the board it's associated with */
Включает охранников будет частью решения этого вопроса.
Пример Wikipedia:
#ifndef GRANDFATHER_H
#define GRANDFATHER_H
struct foo {
int member;
};
#endif
http://en.wikipedia.org/wiki/include_guard
Другая часть, как отмечена несколькими другими, направлена на пересылку. ( http://en.wikipedia.org/wiki/forward_Reference )
Вы можете частично объявить одну из структур над другим, подобным так:
#ifndef GRANDFATHER_H
#define GRANDFATHER_H
struct bar;
struct foo {
int member;
};
#endif
, как так:
//Board.h
#ifndef BOARD_H
#define BOARD_H
strunct move_t; //forward declaration
typedef struct move_t Move;
//...
#endif //BOARD_H
//Move.h
#ifndef MOVE_H
#define MOVE_H
#include "Move.h"
typedef struct board_t Board;
//...
#endif //MOVE_H
таким образом Board.h
может быть скомпилирован без зависимости от MOVE .H
, и вы можете включить Board.h
из move.h
, чтобы сделать его содержание там.
Вам нужно иметь один из них первым. Сделайте прямое DECAL в одном из них и имейте, что один для примера
#ifndef move
struct move;
#endif
может быть частью файла POWER.H.
И
#ifndef board
struct board;
#endif
может быть частью файла move.h
, то вы можете добавить их в любой заказ.
Редактировать Как было отмечено в комментариях ... Я предполагал, что использование Typedef Construction следующим образом для структуры доски
typedef struct {…} board;
, поскольку я никогда не видел никого, используя структуры в C без типов, я сделал это предположение ... возможно Вещи изменились с прошлого года, когда я закодировал в C (Yikies .... Это было как 15 лет назад)
От K & R языка программирования C (P 91 "Условное включение" в мою копию), с некоторыми настройками для вас:
#if !defined (BOARD_H)
#define BOARD_H
/* contents of board.h go here */
#endif
и то же самое для move.h
таким образом После того, как заголовок был включен один раз, он не будет включен в комплект снова, так как имя «Board_H» уже определено для препроцессора.
Цирусные зависимости являются болью в заднице и должны быть устранены везде, где это возможно. В дополнение к предложениям передней декларации, приведенные до сих пор (Alok, является лучшим примером), я хотел бы бросить еще одно предложение в работы: нарушать взаимную зависимость между доской и переместиться путем введения третьего типа (вызовите его BoardMovAsococ для иллюстрации; Я уверен, что вы можете придумать менее засоснение):
#ifndef H_BOARD_MOVE_ASSOC
#define H_BOARD_MOVE_ASSOC
#include "Move.h"
#include "Board.h"
struct BoardMoveAssoc {
Move m;
Board b;
};
...
#endif
по этой схеме, доску и шагом не нужно ничего знать друг о друге; Любые ассоциации между ними управляются типа POWERMOVEASOSOCOC. Точная структура будет зависеть от того, как должны быть связаны движение и доска; E.g., если несколько движений отображаются на одной доске, структура может выглядеть больше похожей на
struct BoardMoveAssoc {
Move m[NUM_MOVES] // or Move *m;
Board b;
};
таким образом, вам не нужно беспокоиться о пересылки и неполных типов. Вы представляете третий тип в микс, но я считаю, что это будет легче понять и поддерживать.
Я предпочитаю следующее решение (требуйте Джанго > = 1,0).
settings.py
INSTALLED_APPS+= ('django.contrib.flatpages',)
urls.py
urlpatterns+= patterns('django.contrib.flatpages.views',
url(r'^about-us/$', 'flatpage', {'url': '/about-us/'}, name='about'),
url(r'^license/$', 'flatpage', {'url': '/license/'}, name='license'),
)
[...]
<a href="{% url about %}"><span>{% trans "About us" %}</span></a>
<a href="{% url license %}"><span>{% trans "Licensing" %}</span></a>
[...]
from django.core.urlresolvers import reverse
[...]
reverse('license')
[...]
Это путь вам не нужно использовать django.contrib.flatpages.middleware.FlatpageFallbackMiddleware
, и реверс работает как обычно, не записывая столько кода, сколько в других решениях.
Ура.
-121--2178529- Во-первых, вам не хватает включить охранников в файлы .h
, поэтому вы включаете их рекурсивно. Это плохо.
Во-вторых, можно сделать форвардное объявление. В Move.h
:
/* Include guard to make sure your header files are idempotent */
#ifndef H_MOVE_
#define H_MOVE_
#include "Board.h"
/* Now you can use struct Board */
struct Move { struct Board *board; };
#endif
В Board.h
:
#ifndef H_BOARD_
#define H_BOARD_
struct Move; /* Forward declaration. YOu can use a pointer to
struct Move from now on, but the type itself is incomplete,
so you can't declare an object of the type itself. */
struct Board { struct Move *move; }; /* OK: since move is a pointer */
#endif
Обратите внимание, что если необходимо объявить объекты struct Move
и struct Board
(а не указывать на один из них) в обоих файлах, этот метод не будет работать. Это связано с тем, что один из типов является неполным типом во время синтаксического анализа одного из файлов ( struct Move
в приведенном выше примере).
Таким образом, если необходимо использовать типы в обоих файлах, необходимо выделить определения типов: иметь заголовочные файлы, которые определяют struct Move
и struct Board
, и ничего другого (что-то подобное моему примеру выше), а затем использовать другой заголовочный файл, который ссылается на struct Move
и struct Board
.
Конечно, нельзя, чтобы struct Move
содержали struct Board
и struct Board
содержали struct Move
одновременно - это будет бесконечная рекурсия, и структура