C header file loops

2019-02-16 15:25发布

I have a couple of header files, which boil down to:

tree.h:

#include "element.h"

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

and element.h:

#include "tree.h"

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

The problem is that they both reference each other, so tree needs element to be included, and element needs tree to be included.

This doesn't work because to define the 'tree' structure, the element structure must be already known, but to define the element structure, the tree structure must be known.

How to resolve these types of loops (I think this may have something to do with 'forward declaration'?)?

10条回答
狗以群分
3楼-- · 2019-02-16 16:02

IMHO the best way is to avoid such loops because they are a sign of physical couping that should be avoided.

For example (as far as I remember) "Object-Oriented Design Heuristics" purpose to avoid Include Guards because they only mask the cyclic (physical) dependency.

An other approach is to predeclare the structs like this:

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; };

查看更多
Evening l夕情丶
4楼-- · 2019-02-16 16:08

The correct answer is to use include guards, and to use forward declarations.

Include Guards

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

// Your code here

#endif
/* end foo.h */

Visual C++ also supports #pragma once. It is a non standard preprocessor directive. In exchange for compiler portability, you reduce the possibility of preprocessor name collisions and increase readability.

Forward Declarations

Forward declare your structs. If the members of a struct or class are not explicitly needed, you can declare their existence at the beginning of a header file.

struct tree;    /* element.h */
struct element; /* tree.h    */
查看更多
仙女界的扛把子
5楼-- · 2019-02-16 16:11

I don't like forward declarations cause they are redundant and buggy. If you want all your declarations in the same place then you should use includes and header files with include guards.

You should think about includes as a copy-paste, when the c preprocesor finds an #include line just places the entire content of myheader.h in the same location where #include line was found.

Well, if you write include guards the myheader.h's code will be pasted only one time where the first #include was found.

If your program compiles with several object files and problem persists then you should use forward declarations between object files (it's like using extern) in order to keep only a type declaration to all object files (compiler mixes all declarations in the same table and identifiers must be unique).

查看更多
登录 后发表回答