Как будто вы пытаетесь получить доступ к объекту, который является null
. Рассмотрим ниже пример:
TypeA objA;
. В это время вы только что объявили этот объект, но не инициализировали или не инициализировали. И всякий раз, когда вы пытаетесь получить доступ к каким-либо свойствам или методам в нем, он будет генерировать NullPointerException
, что имеет смысл.
См. Также этот пример:
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
Я думаю, что проблемой здесь не являются пропавшие без вести, включают защиту, но то, что этим двум структурам нужен друг друг в их определении. Таким образом, это - тип, определяют проблема яйца и 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 больше.
необходимо также поместить включать-защиту вокруг заголовочных файлов также.
Решающее наблюдение здесь состоит в том, что элемент не должен знать структуру дерева, так как это только содержит указатель на него. То же для дерева. Все, что каждый должен знать, - то, что там существует тип с соответствующим именем, не, что находится в нем.
Так в tree.h, вместо:
#include "element.h"
сделайте:
typedef struct element_ element;
Это "объявляет" типы "элемент", и "элемент структуры _" (говорит, что они существуют), но не "определяет" их (скажите, что они). Все необходимо сохранить указатель на вздор, - то, что вздор объявляется, не, что он определяется. Только если Вы хотите к отсрочке, которую это (например, для чтения участников) делает Вам нужно определение. Код в Вашем ".c" файле должен сделать это, но в этом случае Ваши заголовки не делают.
Некоторые люди создают единственный заголовочный файл, которые передают - объявляет все типы в кластере заголовков, и затем каждый заголовок включает это, вместо того, чтобы удаться, в каких типах он действительно нуждается. Это не важно и не абсолютно глупо.
ответы о включают защиту, являются неправильными - они - хорошая идея в целом, и необходимо читать о них и вовлечь себя некоторые, но они не решают проблему в частности.
Корректный ответ должен использовать, включают защиту, и использовать предописания.
/* 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 */
Считайте приблизительно предописания .
т.е.
// 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
Они известны как "разовые заголовки". См. http://developer.apple.com/DOCUMENTATION/DeveloperTools/gcc-4.0.1/cpp/Once_002dOnly-Headers.html#Once_002dOnly-Headers
Включайте защиту, полезны, но не решают проблему плаката, которая является рекурсивной зависимостью от двух структур данных.
решение здесь состоит в том, чтобы объявить дерево и/или элемент как указатели на структуры в заголовочном файле, таким образом, Вы не должны включать .h
Что-то как:
struct element_;
typedef struct element_ element;
Наверху tree.h должен быть достаточно для устранения необходимости включать element.h
С частичным объявлением как это, можно только сделать вещи с указателями элемента, которые не требуют, чтобы компилятор знал что-либо о расположении.
По моему скромному мнению, лучший способ состоит в том, чтобы избежать таких циклов, потому что они - знак физического couping, которого нужно избежать.
, Например (насколько я помню) "Объектно-ориентированная Эвристика Дизайна" цель избежать Включает гвардию, потому что они только маскируют циклическую (физическую) зависимость.
другой подход должен предварительно объявить структуры как это:
element.h:
struct tree_;
struct element_
{
struct tree_ *tree_parent;
char *name;
};
tree.h: элемент структуры _; структура tree_ {структура tree_* first_child; структура tree_* next_sibling; международный тег; структура element_ *obj;};
Прямое объявление - это способ, с помощью которого вы можете гарантировать, что будет определенная структура, которая будет определена позже.