Frage

Ich habe ein paar von Header-Dateien, die zu einkochen:

tree.h:

#include "element.h"

typedef struct tree_
{
    struct *tree_ first_child;
    struct *tree_ next_sibling;
    int tag;
    element *obj;
    ....
} tree;

und element.h:

#include "tree.h"

typedef struct element_
{
    tree *tree_parent;
    char *name;
    ...
} element;

Das Problem ist, dass sie beide sich gegenseitig referenzieren, so Baumelement muss aufgenommen werden, und das Element muss Baum aufgenommen werden.

Das ist nicht da funktioniert die ‚Baum‘ Struktur zu definieren, muss die Elementstruktur bereits bekannt sein, aber die Elementstruktur, die Baumstruktur zu definieren, muss bekannt sein.

Wie diese Art von Schleifen zu lösen (Ich denke, das könnte etwas mit ‚forward-Deklaration‘? Zu tun)?

War es hilfreich?

Lösung

Ich denke, das Problem hier ist nicht die fehlende umfassen Wache aber die Tatsache, dass die beiden Strukturen in ihrer Definition sie brauchen. Es ist also eine Art hann und Ei-Problem zu definieren.

Die Art, wie diese in C oder C ++ zu lösen, ist nach vorn Erklärungen von der Art zu tun. Wenn Sie die Compiler sagen, dass Element eine Struktur von einer Art ist, kann der Compiler einen Zeiger darauf erzeugen.

z.

Innerhalb tree.h:

// tell the compiler that element is a structure typedef:
typedef struct element_ element;

typedef struct tree_ tree;
struct tree_
{
    tree *first_child;
    tree *next_sibling;
    int tag;

    // now you can declare pointers to the structure.
    element *obj;
};

Auf diese Weise müssen Sie mehr nicht element.h innerhalb tree.h umfassen.

Sie sollten auch setzen umfassen Wachen um Ihren Kopf Dateien auch.

Andere Tipps

Crucial Beobachtung hier ist, dass das Element muss nicht die Struktur des Baumes wissen, da es nur einen Zeiger auf sie hält. Das gleiche gilt für den Baum. jeder muss wissen alle, dass es einen Typ mit dem entsprechenden Namen vorhanden ist, nicht das, was ist drin.

So in tree.h statt:

#include "element.h"

tun:

typedef struct element_ element;

Dieses „erklärt“ die Typen „Element“ und „struct element_“ (sagt sie existieren), aber nicht „definieren“, um sie (sagen, was sie sind). Alles, was Sie ist ein Zeiger-to-blah speichern müssen, dass blah deklariert wird, nicht, dass sie definiert ist. Nur wenn Sie es Ehrerbietung wollen (zum Beispiel die Mitglieder zu lesen) haben Sie die Definition benötigen. Code in Ihrer „.c“ Datei muss das tun, aber in diesem Fall Ihre Header nicht.

Einige Leute erstellen eine einzelne Header-Datei, die alle Typen in einem Cluster von Header voraus erklärt, und dann wird jeder Header enthält, dass, anstatt zu arbeiten heraus, welche Arten es wirklich braucht. Das ist weder wichtig noch ganz dumm.

Die Antworten zu schließen Wachen sind falsch -. Sie eine gute Idee, im Allgemeinen sind, und Sie sollten über sie lesen und sich einige, aber sie lösen nicht das Problem insbesondere

Die richtige Antwort ist Wächter zu verwenden ist, und Erklärungen zu verwenden, vor.

Neue Guards

/* begin foo.h */
#ifndef _FOO_H
#define _FOO_H

// Your code here

#endif
/* end foo.h */

Visual C ++ Pragma auch einmal unterstützt. Es ist ein nicht-Standard Präprozessordirektive. Im Gegenzug für die Compiler-Portabilität, die Möglichkeit des Vorprozessors Namenskollisionen reduzieren und die Lesbarkeit erhöhen.

Vorwärtsdeklarationen

Weiterleiten Ihrer structs erklären. Wenn die Mitglieder einer Struktur oder Klasse nicht explizit benötigt werden, können Sie ihre Existenz zu Beginn einer Header-Datei deklariert werden.

struct tree;    /* element.h */
struct element; /* tree.h    */

Lesen Sie mehr über forward-Deklarationen .

dh.


// tree.h:
#ifndef TREE_H
#define TREE_H
struct element;
struct tree
{
    struct element *obj;
    ....
};

#endif

// element.h:
#ifndef ELEMENT_H
#define ELEMENT_H
struct tree;
struct element
{
    struct tree *tree_parent;
    ...
};
#endif

Neue Wachen sind nützlich, aber befassen sich nicht das Problem des Plakats, das die rekursive Abhängigkeit von zwei Datenstrukturen ist.

Die Lösung hier ist Baum zu erklären und / oder Element als Zeiger innerhalb der Header-Datei Structs, so dass Sie die .h nicht enthalten müssen

So etwas wie:

struct element_;
typedef struct element_ element;

An der Spitze der tree.h sollte ausreichen, um den Bedarf zu entfernen element.h einschließen

Mit einem Teil Erklärung wie dies nur tun können, Dinge mit dem Element Zeiger, die nicht den Compiler erfordern etwas über das Layout kennen.

IMHO der beste Weg, solche Schleifen zu vermeiden, weil sie ein Zeichen des physischen couping ist, die vermieden werden sollten.

Zum Beispiel (soweit ich mich erinnere) „Objektorientiertes Design Heuristik“ Zweck umfassen Guards zu vermeiden, weil sie nur die zyklische (physische) Abhängigkeit maskieren.

Ein anderer Ansatz ist es, die Strukturen so predeclare:

element.h:
struct tree_;
struct element_
  {
    struct tree_ *tree_parent;
    char *name;
  };

tree.h: struct element_; struct tree_ { struct tree_* first_child; struct tree_* next_sibling; int tag; struct element_ *obj; };

Vorwärts-Deklaration ist die Art und Weise, mit der Sie garantieren können, dass es eine Art von Struktur sein, die später definiert werden.

Ich mag vorwärts keine Erklärungen, weil sie überflüssig und Buggy sind. Wenn Sie alle Ihre Erklärungen an der gleichen Stelle wollen, dann sollten Sie enthalten verwenden und Header-Dateien mit Schutztruppe geschaffen werden.

Sie sollten darüber nachdenken, enthält als Copy-Paste, wenn die c preprocesor nur eine # include-Zeile findet den gesamten Inhalt myheader.h an der gleichen Stelle platziert, wo #include Linie gefunden wurde.

Nun, wenn Sie schreiben sind bewacht den Code des myheader.h wird nur einmal eingefügt werden, wo die erste #include gefunden wurde.

Wenn Ihr Programm mit mehreren Objektdateien und Problem stellt weiterhin besteht, dann sollten Sie Vorwärtsdeklarationen zwischen Objektdateien zu verwenden (es ist wie extern verwenden), um nur eine Typdeklaration für alle Objektdateien zu halten (Compiler alle Erklärungen in der gleichen Tabelle mischen und Kennungen müssen eindeutig sein).

Eine einfache Lösung ist, einfach nicht separate Header-Dateien hat. Nach allem, wenn sie voneinander abhängig sind sind Sie nie ohne das andere nicht benutzen wollen, so sie, warum trennen? Sie können separate .c-Dateien, die beide den gleichen Header verwenden, aber die gezieltere Funktionalität.

Ich weiß, dass dies nicht die Frage, nicht beantworten, wie richtig die ganzen fancy stuff zu bedienen, aber ich fand es hilfreich, als ich für eine schnelle Lösung zu einem ähnlichen Problem suchen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top