2

FileTwo.hの内部

#ifndef FILETWO
#define FILETWO
#include"FileOne.h"
class FileOne ;
class FileTwo
{
public:
    int Test(FileOne One){
        return (One.var1+One.var2);}

    FileTwo(void);
    ~FileTwo(void);
};
#endif

FileOne.hの内部

#ifndef FILEONE
#define FILEONE
#include"FileTwo.h"
class FileTwo ;
class FileOne
{
private:
     int var1 , var2 , var3 ;
public :
    friend int FileTwo::Test(FileOne One);
    FileOne(){
        var1= 12;var2 = 24;
    }

};
#endif

main.cppの内部

#include<iostream>
using namespace std ;
#include"FileOne.h"
#include"FileTwo.h"

int main(){
FileOne one ;
FileTo two ;
cout<<two.Test(one);
}

コンパイル中に次のエラーが発生しました

   1-- error C2027: use of undefined type 'FileOne' c:\users\e543925\documents\visual studio 2005\projects\myproject\filetwo.h
   2--error C2027: use of undefined type 'FileOne'  c:\users\e543925\documents\visual studio 2005\projects\myproject\filetwo.h  

   3--error C2228: left of '.var1' must have class/struct/union c:\users\e543925\documents\visual studio 2005\projects\myproject\filetwo.h
   4--error C2228: left of '.var2' must have class/struct/union c:\users\e543925\documents\visual studio 2005\projects\myproject\filetwo.h

FileTwo.cpp内でテスト関数を定義するような回避策を1つ見つけました。しかし、私は上記の問題がヘッダーファイル内でどのように解決できるか知りたいです。

4

4 に答える 4

2

ここでの問題は、両方のファイルを互いに含めていることです。コンパイラが parse を実行するFileOne.hと、 が含まれFileTwo.hているため、それを読み取り、スキップしてFileOne.h(インクルード ガードのおかげです。そうしないと、無限ループに陥ります)、FileOneまだ定義されていない class を使用しようとします。

実際には、これは;に含まFileOne.hれていないかのようです。型 ( ) がまだ定義されていないため、 のFileTwo.hメソッドを呼び出すことはできません。フレンドクラスとは関係ありません。またはまだです (この問題については後で説明します)。OneFileOne

FileTwoあなたのコードから、クラスを使用してテストしたいようですFileOne。この場合、FileOneは について多くを知る必要はなくFileTwo、単にその内部を確認できるようにします (別名、フレンドにします)。したがって、コードは次のように要約できます。

FileOne.h:

#ifndef FILEONE
#define FILEONE
class FileOne
{
  friend class FileTwo; // This is all FileOne needs from FileTwo
private:
  int var1 , var2 , var3 ;
public :
  FileOne(){
    var1= 12;var2 = 24;
  }
};
#endif

FileTwo.h:

#ifndef FILETWO
#define FILETWO
#include"FileOne.h"
class FileTwo
{
public:
  int Test(FileOne One) {
    return (One.var1+One.var2);
  }

  FileTwo();
  ~FileTwo();
};
#endif
于 2013-01-03T08:17:36.157 に答える
1

少なくともこの単純な例では、FileOne.h内部を含める必要はありません。FileTwo.hただし、一般的に、循環インクルードは、デザインに問題があることを意味します。

単一のメソッドだけでなく、クラス全体を友達にする必要があります。これはクラス間の主要な結合を導入するので、私もこの友情を再考したいと思います。パブリックメソッドで同じことを達成することはできませんか?

于 2013-01-03T08:14:26.270 に答える
1

あなたが持っているのは循環依存であり、不完全な型宣言を使用して解決できます。現状では、コードは両方のファイルで完全な型宣言を必要とします。

1) FileOne.h: friend int FileTwo::Test(FileOne One);(コンパイラに のメンバー関数を見つけるように要求していますFileTwo)

2) FileTwo.h 内: int Test(FileOne One){ return (One.var1+One.var2);}(コンパイラに のメンバー変数を見つけるように要求していますFileOne)

少なくとも 1 つのファイルで不完全な型宣言を使用する必要があります ( class FileOne; class FileTwo;)。あなたはすでにそれをやろうとしていますが、#includeディレクティブを使用するとそれが損なわれます。次の 2 つのオプションがあります。

1 つは、クラス全体としてFileTwoのフレンドを作成することです。これは、不完全な型を使用することで許可されます。FileOneを削除し#include "FileTwo.h"ます。

あなたがすでに自分で見つけた他のもの:

FileTwo.cpp 内で Test 関数を定義するなどの回避策を 1 つ見つけました。

#include "FileOne.h"その場合、FileTwo.h から削除します。

于 2013-01-03T08:26:30.023 に答える
1

あなたの友達宣言は問題ありません。あなたが抱えている問題は ですcircular include。クラス実装の1つをcppファイルに入れることで、循環インクルードを壊すことができます。

たとえば、FileTwo クラスを FileTwo.h に分割すると、FileTwo.cpp で問題が解決するはずです。または、宣言しfriend FileTwo;てから、1 つの前方宣言で十分です。

FileOne.h

#ifndef FILEONE
#define FILEONE

class FileTwo;
class FileOne
{
private:
     int var1 , var2 , var3 ;
public :
    friend FileTwo;
    FileOne(){
        var1= 12;var2 = 24;
    }

};
#endif

FileTwo.h

#ifndef FILETWO
#define FILETWO

#include "FileOne.h"
class FileTwo
{
public:
   inline int Test(FileOne One)
    {
      return (One.var1+One.var2);
    }

    FileTwo(void){}
    ~FileTwo(void){}
};
#endif
于 2013-01-03T08:34:49.860 に答える