2

考虑以下示例。它由两个头文件组成,声明了两个不同的命名空间:

// a1.h
#pragma once
#include "a2.h"

namespace a1 
{
    const int x = 10;
    typedef a2::C B;
}

第二个是

// a2.h    
#pragma once
#include "a1.h"

namespace a2 {
  class C {
  public:
    int say() {
      return a1::x; 
    }
  };
}

和一个单一的源文件,main.cpp

#include <iostream>
#include "a1.h"
#include "a2.h"

int main()
{
  a2::C c;
  std::cout << c.say() << std::endl;
}

这样它就不会编译(尝试过 GCC 和 MSVC)。错误是a1未声明命名空间(Windows 上的 C2653)。如果您以main.cpp这种方式更改包含顺序:

#include "a2.h"
#include "a1.h"

您会收到一条对称错误消息,即a2未声明命名空间。

有什么问题?

4

3 回答 3

11

您需要在头文件中使用前向声明,因为您有循环引用。像这样的东西:

// a1.h
#pragma once

namespace a2 {
    class C;
}

namespace a1 
{
    const int x = 10;
    typedef a2::C B;
}
于 2008-12-18T19:25:21.160 回答
3

只是一个猜测,但您的包含引用是循环的。这意味着编译器无法确定首先编译哪个头文件。a1 引用 a2 引用 a1。

如果可能,合并/重组文件,以便有一个非循环的包含链。

希望有帮助!

于 2008-12-18T19:21:04.850 回答
1

当您首先包含 a1.h 时,它会在声明任何内容之前立即尝试包含 a2.h

a2.h 引用了命名空间 a1 中尚未声明的内容

当您首先包含 a2.h 时,它会在声明任何内容之前立即尝试包含 a1.h

a1.h 引用了命名空间 a2 中尚未声明的内容

从您没有使用的 a1.h 中删除 typedef 并且不包括 a2.h 会删除循环。

或者像其他评论者一样,转发声明 C 类。

// a1.h
#pragma 一次
//#包括“a2.h”

命名空间 a1
{
    常量 int x = 10;
// typedef a2::CB;
}
于 2008-12-18T19:59:33.383 回答