2

次の例を考えてみましょう。これは2つのヘッダーファイルで構成され、2つの異なる名前空間を宣言します。

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

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

2つ目は

// 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 は、a1 を参照する a2 を参照します。

可能であれば、ファイルをマージ/再編成して、インクルードの非循環チェーンが存在するようにします。

それが役立つことを願っています!

于 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 once
//#include "a2.h"

名前空間 a1
{
    const int x = 10;
// typedef a2::CB;
}
于 2008-12-18T19:59:33.383 に答える