문제

두 개의 헤더 파일이 있습니다.

Tree.h :

#include "element.h"

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

그리고 요소 .H :

#include "tree.h"

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

문제는 둘 다 서로를 참조하기 때문에 트리에는 요소가 포함되어야하고 요소는 트리를 포함해야한다는 것입니다.

'트리'구조를 정의하기 위해서는 요소 구조를 이미 알고 있어야하지만 요소 구조를 정의하려면 트리 구조를 알고 있어야합니다.

이러한 유형의 루프를 해결하는 방법 ( '전진 선언'과 관련이있을 수 있습니까?)?

도움이 되었습니까?

해결책

여기서 문제는 누락 된 가드가 아니라 두 구조가 서로의 정의에서 서로를 필요로한다는 사실이라고 생각합니다. 따라서 Hann과 계란 문제를 정의하는 유형입니다.

C 또는 C ++에서이를 해결하는 방법은 유형에 대한 선언을 수행하는 것입니다. 컴파일러에 요소가 일종의 구조라고 말하면 컴파일러는 포인터를 생성 할 수 있습니다.

예를 들어

내부 트리 .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;
};

그렇게하면 더 이상 tree.h 내부에 요소를 포함 할 필요가 없습니다.

또한 헤더 파일 주위에 포함 구내를 넣어야합니다.

다른 팁

여기서 중요한 관찰은 요소가 트리의 구조를 알 필요가 없다는 것입니다. 나무에 대해서도 마찬가지입니다. 각각 알아야 할 모든 것은 관련 이름이 아닌 관련 이름이있는 유형이 있다는 것입니다.

그래서 tree.h에서 : 대신 :

#include "element.h"

하다:

typedef struct element_ element;

이것은 "유형"요소 "및"struct element_ "(존재 함을 말하면)를 선언하지만 (존재하는지)"정의 "하지는 않습니다. 포인터 투 블라를 저장하는 데 필요한 것은 Blah가 정의 된 것이 아니라 선언된다는 것입니다. 회의를 원한다면 (예 : 멤버를 읽기 위해) 정의가 필요합니까? ".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

포함 경비원은 유용하지만 두 개의 데이터 구조에 대한 재귀 적 의존성 인 포스터의 문제를 해결하지 마십시오.

여기서 솔루션은 트리 및/또는 요소를 헤더 파일 내의 스트러크에 대한 포인터로 선언하는 것입니다. 따라서 .h를 포함 할 필요가 없습니다.

같은 것 :

struct element_;
typedef struct element_ element;

Tree.h의 상단에는 요소를 포함시킬 필요성을 제거하기에 충분해야합니다 .H

이와 같은 부분 선언을 사용하면 컴파일러가 레이아웃에 대해 알 필요가없는 요소 포인터로만 작업을 수행 할 수 있습니다.

IMHO 가장 좋은 방법은 그러한 루프를 피하는 것입니다. 피해야 할 물리적 쿠킹의 표시이기 때문입니다.

예를 들어 (내가 기억하는 한) "객체 지향 디자인 휴리스틱" 경비원은 주기적 (물리적) 의존성 만 숨기기 때문에 피하는 목적.

다른 접근법은 다음과 같은 문자를 전제하는 것입니다.

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 태그; struct element_ *obj; };

Forward DeMaratio는 나중에 정의 될 구조의 타이오가있을 것을 보장 할 수있는 방법입니다.

나는 전진 선언이 중복되고 버그가되는 것을 좋아하지 않습니다. 모든 선언을 같은 장소에 원한다면 가드 포함 포함 및 헤더 파일을 사용해야합니다.

C 프리 프로세서가 #include 라인을 찾을 때 마이 헤드러의 전체 내용을 #include 라인을 찾은 동일한 위치에 배치 할 때 카피 페이스트로 포함됩니다.

글쎄, 당신이 Guards를 작성하면 MyHeader.h의 코드는 첫 번째 #include가 발견 된 한 번만 붙여 넣습니다.

프로그램이 여러 객체 파일로 컴파일되고 문제가 지속되면 모든 객체 파일에 유형 선언 만 유지하려면 객체 파일 간의 전달 선언을 사용해야합니다 (컴파일러는 동일한 테이블의 모든 선언을 믹스하고 식별자가 필요합니다. 독특하다).

간단한 솔루션은 별도의 헤더 파일이없는 것입니다. 결국, 그들이 서로에 의존한다면 다른 사람 없이는 결코 사용하지 않을 것입니다. 왜 분리합니까? 동일한 헤더를 사용하지만 더 집중된 기능을 제공하는 별도의 .C 파일을 가질 수 있습니다.

나는 이것이 모든 멋진 것들을 올바르게 사용하는 방법에 대한 질문에 대답하지 않는다는 것을 알고 있지만, 비슷한 문제에 대한 빠른 수정을 찾을 때 도움이된다는 것을 알았습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top