为什么头文件不能互相包含?

时间:2018-10-03 02:43:45

标签: c++ include header-files circular-dependency

为什么我不能在C ++中做这样的事情?

A.h:

#ifndef A_H
#define A_H
#include "B.h"

struct A {
    int a;
};

void doStuff1 (B b);  // Error here

#endif

B.h:

#ifndef B_H
#define B_H
#include "A.h"

struct B {
    int b;
};

void doStuff2 (A a);  // Error here

#endif

我得到一个错误,'A' was not declared in this scope'B'相同。 我知道前向声明,但是我想看看是否有可能将这样的设置作为按值传递而不是按引用/指针进行设置。如果AB实际上在编译器到达该代码时就已声明,为什么编译器会表现出这样的行为?

2 个答案:

答案 0 :(得分:2)

基本课程:在解析任何C ++之前先处理包含文件。它们由预编译器处理。

比方说,A.h被包含在B.h之前。你会得到这样的东西:

#ifndef A_H
#define A_H

// ----- B.h include -----    

#ifndef B_H
#define B_H
#include "A.h" // A_H is defined, so this does nothing

struct B {
    int b;
};

void doStuff2 (A a);  // Error here

#endif

// ----- B.h include -----

struct A {
    int a;
};

void doStuff1 (B b);  // Error here

#endif

这时,C ++编译器可以接管并开始解析内容。它将尝试找出doStuff2的参数是什么,但是A尚未定义。反之亦然。在这两种情况下,您都依赖于尚未定义的类型。

所有这一切都意味着您的依存关系混乱。传递值不是问题。必须在方法之前定义类型。仅此而已-请参见下面的示例。

// Example program
#include <iostream>
#include <string>

// data_types.h
struct A
{
    int x;
};

struct B
{
    int y;
};

using namespace std;
// methods_A.h
void foo(A a)
{
    a.x = 3;
    cout << "a: " << a.x << endl;
}

// methods_B.h
void bar(B b)
{
    b.y = 4;
    cout << "b: " << b.y << endl;
}

int main()
{
   A first;
   B second;
   first.x = 0;
   second.y = 100;
   foo(first);
   bar(second);
   cout << "A: " << first.x << ", B: " << second.y << endl;
}

示例输出

a: 3
b: 4
A: 0, B: 100

答案 1 :(得分:1)

您有一个循环包含。您需要将它们分成不同的头文件,例如让A.hB.h仅声明结构/类,而让其他头文件声明函数。

也可以通过使用前向声明并通过引用传递来解决该问题:

struct A;
struct B;

void doStuff1(A& a);
void doStuff2(B& b);