2012-05-11 5 views
13

C++ Primerの本によれば、クラスメンバ関数をクラス全体(634ページ)ではなく、別のクラスのフレンドとして指定することができます。クラスメンバ関数を別のクラスのフレンドとして指定しますか?

はその後、私はこのコードをテストした:

class A 
{ 
public: 
    friend void B::fB(A& a); 
    void fA(){} 
}; 
class B 
{ 
public: 
    void fB(A& a){}; 
    void fB2(A& a){}; 
}; 

私はちょうど(FBを望んでいた)は、クラスAの友人になる、全体ではなくクラスBが、約コードは、エラーを生成:'B' : is not a class or namespace name。 (私はVisual C++ 2005を使用しています)

答えて

14

は、Aの前にBの定義を入れてみてください:

class A; // forward declaration of A needed by B 

class B 
{ 
public: 
    // if these require full definition of A, then put body in implementation file 
    void fB(A& a); // Note: no body, unlike original. 
    void fB2(A& a); // no body. 
}; 

class A 
{ 
public: 
    friend void B::fB(A& a); 
    void fA(){} 
}; 

Aが必要Bの完全な定義。ただし、Bは約Aを知る必要がありますが、完全な定義は必要ないため、Aという前方宣言が必要です。

+0

しかし、FB(A&A)に私がa.variable、例えばA内の変数にアクセスするために使用する場合、 Aはまだ定義されていないので、違法となる。 – ipkiss

+1

@ipkissはい。ヘッダークラ​​ス宣言の場合は、完全な定義が必要です。しかし、別のインプリメンテーションファイルで実行した場合、Aの完全な宣言を含めることができます。 – juanchopanza

2

これを実行するには、Aの定義の前に完全な定義Bを知る必要があります。

だから、前方フルタイプを必要としないB以来、Aを宣言し、周りの定義を切り替える:

class A; 
class B 
{ 
public: 
    void fB(A& a){}; 
    void fB2(A& a){}; 
}; 
class A 
{ 
public: 
    friend void B::fB(A& a); 
    void fA(){} 
}; 
0

第1に、クラスAを宣言して、クラスBの定義で可視にする。クラスBのフレンド関数を含むクラスAを定義します。

0

まず、特定のクラス名を使用する前に、まずそれを宣言する必要があります。 Class Bが最初に宣言される前にClass Aで使用しているので、Class Bの前方宣言が必要です。

第2に、両方のクラスが定義された後に関数を定義する必要があります(これは両方のクラスの変数を使用しています - ここではfriendが機能します)。そうでなければエラーに直面するかもしれません。 put_bataは、彼らは私たちは、クラスの前方宣言があったが、下記のコードはうまく動作します場合にも定義されています前に、ロールとIDにアクセスしようとして

#include<iostream> 

using namespace std; 

class alpha1; 

class alpha2 
{ 
    public: 

     void put_bata(int a,int b); 
}; 

void alpha2 :: put_bata(int a,int b) 
{ 
    alpha1 net; 

    net.roll=a; 

    net.id=b; 

    net.get_data(); 
} 

class alpha1 
{ 
    int roll; 

    int id; 

    public: 

     void get_data(void) 
     { 
      cout<<roll<<endl<<id<<endl; 
     } 

     friend void alpha2 :: put_bata(int a,int b); 
}; 

int main() 
{ 
    alpha2 gamma; 

    gamma.put_bata(5,6); 

    return 0; 
} 

例えば

は私たちにエラーが表示されます。あなたが内部のFBのデータメンバー(& a)のAはまだ定義されていないためにアクセスすることができない問題について

#include<iostream> 

using namespace std; 

class alpha1; 

class alpha2 
{ 
    public: 

     void put_bata(int a,int b); 
}; 

class alpha1 
{ 
    int roll; 

    int id; 

    public: 

     void get_data(void) 
     { 
      cout<<roll<<endl<<id<<endl; 
     } 

     friend void alpha2 :: put_bata(int a,int b); 
}; 

void alpha2 :: put_bata(int a,int b) 
{ 
    alpha1 net; 

    net.roll=a; 

    net.id=b; 

    net.get_data(); 
} 


int main() 
{ 
    alpha2 gamma; 

    gamma.put_bata(5,6); 

    return 0; 
} 
0

@juanchopanza @ipkiss 。それを別のファイルに定義し、それを含む代わりに、fB(A & a)がAのデータメンバーを見ることができるように、クラスAの定義の後に関数fB(A & a)を定義するだけでよい。

2

コンパイラは(通常は上から)コードの読み取りを開始し、それがこの行に出会う:

friend void B::fB(A& a);

次に、コンパイラは、あなたがこのB::によって何を意味するか理解していません。コードの後半でこのクラスを定義したとしても、コンパイラはそれを知りません。したがって、定義がコードの後半にある場合は、クラスの前方宣言(class Name;)を実行することは、通常は実践するのが良いことです。

2

コンパイラは(通常は上から)コードのコンパイルを開始し、それがこのライン遭遇したとき:この時点で

friend void B::fB(A& a); 
  1. を、それがエラーをスローので、コンパイラは(Bの型情報については考えていません'B':クラスまたは名前空間名ではありません)。
  2. クラスBの前方宣言によって、コンパイラはBの型についてクラスを知っています。クラスB

///////////////

class B; 
class A 
{ 
public: 
    friend void B::fB(A& a); 
    void fA(){}; 
}; 
class B 
{ 
public: 
    void fB(A& a){}; 
    void fB2(A& a){}; 
}; 
まだ

エラーの前方宣言の後にコードの下

  • 実行!

    です。前方宣言は、プログラマがまだ完全な定義を与えていない識別子の宣言に過ぎないためです。コンパイラはクラスAの前にBを完全に定義する必要があります。

    注:クラスAの定義はBの型に依存しています(つまり、B :: fB)ので、前方宣言だけでは解決できないため、 Bは、クラスAの

    4実行する前にこのコード

    ////////

    class B 
    { 
    public: 
        void fB(A& a){}; 
        void fB2(A& a){}; 
    }; 
    class A 
    { 
    public: 
        friend void B::fB(A& a); 
        void fA(){} 
    }; 
    

    それでもエラーを定義する必要があります!クラス:

    タイプAの引数を持つFB & FB2クラスBのメンバ関数ので、コンパイラはそのクラスAの前方宣言により、我々はコンパイラはA. ノートの型情報を知っているさせることができますの型情報については考えていません解決ステップのように前方宣言のないメンバーのタイプにのみ依存B定義4.

    //////
  • 最終コード
    1. /////////////////

      class A; // forward declaration of A needed by B 
      class B 
      { 
      public: 
          void fB(A& a); 
      }; 
      
      class A 
      { 
          int i; 
      public: 
          friend void fA(A& a); //specifying function fA as a friend of A, fA is not member function of A 
          friend void B::fB(A& a); //specifying B class member function fB as a friend of A 
      }; 
      
      // fA is Friend function of A 
      void fA(A& a) 
      { 
          a.i = 11; // accessing and modifying Class A private member i 
          cout<<a.i<<endl; 
      } 
      
      // B::fB should be defined after class A definition only because this member function can access Class A members 
      void B::fB(A& a) 
      { 
          a.i = 22; // accessing and modifying Class A private member i in Class B member function fB 
          cout<<a.i<<endl; 
      } 
      
      int main() 
      { 
          A a; 
          fA(a); // calling friend function of class A 
      
          B b; 
          b.fB(a); // calling B class member function fB, B:fB is friend of class A 
      
          return 0; 
      } 
      

      6演習:

      // Cyclic dependency 
      #include<iostream> 
      using namespace std; 
      
      class A; 
      
      class B 
      { 
      public: 
          void fB(A& a); 
          friend void A::fA(B& b); //specifying class A's member function fA as a friend of B 
      }; 
      
      class A 
      { 
          int i; 
      public: 
          void fA(B& b); 
          friend void B::fB(A& a); //specifying class B's member function fB as a friend of A 
      }; 
      
      int main() 
      { 
          return 0; 
      } 
      
    +0

    したがって、どのように練習問題を解決しますか? –

    +0

    @BrunoMartinez - これは完璧な解決策ではありません。なぜなら、どちらも周期的にお互いの完全な定義に依存しているからです。この特殊なケースを与える の私の意図は、ソフトウェアデザインにおけるエンティティを切り離すことの重要性を強調し、これに取り組んでいる間にフレンド機能をより明確にすることでした。 これは可能なオプションが共通の友人機能を作成することです – SrinivasPaladugu

    関連する問題