C циклы заголовочного файла

Как будто вы пытаетесь получить доступ к объекту, который является null. Рассмотрим ниже пример:

TypeA objA;

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

См. Также этот пример:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
12
задан Kirill Kobelev 23 December 2016 в 08:42
поделиться

8 ответов

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

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

, Например,

Внутренняя часть 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;
};

Тот путь Вы не должны включать element.h внутри tree.h больше.

необходимо также поместить включать-защиту вокруг заголовочных файлов также.

28
ответ дан 2 December 2019 в 03:39
поделиться

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

Так в tree.h, вместо:

#include "element.h"

сделайте:

typedef struct element_ element;

Это "объявляет" типы "элемент", и "элемент структуры _" (говорит, что они существуют), но не "определяет" их (скажите, что они). Все необходимо сохранить указатель на вздор, - то, что вздор объявляется, не, что он определяется. Только если Вы хотите к отсрочке, которую это (например, для чтения участников) делает Вам нужно определение. Код в Вашем ".c" файле должен сделать это, но в этом случае Ваши заголовки не делают.

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

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

8
ответ дан 2 December 2019 в 03:39
поделиться

Корректный ответ должен использовать, включают защиту, и использовать предописания.

Включают гвардию

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

// Your code here

#endif
/* end foo.h */

, Visual C++ также поддерживает #pragma однажды. Это - нестандартная директива препроцессору. В обмен на мобильность компилятора Вы уменьшаете возможность коллизий названия препроцессора и удобочитаемости увеличения.

Предописания

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

struct tree;    /* element.h */
struct element; /* tree.h    */
3
ответ дан 2 December 2019 в 03:39
поделиться

Считайте приблизительно предописания .

т.е.


// 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
2
ответ дан 2 December 2019 в 03:39
поделиться
0
ответ дан 2 December 2019 в 03:39
поделиться

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

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

Что-то как:

struct element_;
typedef struct element_ element;

Наверху tree.h должен быть достаточно для устранения необходимости включать element.h

С частичным объявлением как это, можно только сделать вещи с указателями элемента, которые не требуют, чтобы компилятор знал что-либо о расположении.

0
ответ дан 2 December 2019 в 03:39
поделиться

По моему скромному мнению, лучший способ состоит в том, чтобы избежать таких циклов, потому что они - знак физического couping, которого нужно избежать.

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

другой подход должен предварительно объявить структуры как это:

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

tree.h: элемент структуры _; структура tree_ {структура tree_* first_child; структура tree_* next_sibling; международный тег; структура element_ *obj;};

0
ответ дан 2 December 2019 в 03:39
поделиться

Прямое объявление - это способ, с помощью которого вы можете гарантировать, что будет определенная структура, которая будет определена позже.

0
ответ дан 2 December 2019 в 03:39
поделиться
Другие вопросы по тегам:

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