12

私は最近friend classC++ の概念について学びました (私は少しググってみましたが、最も重要な部分を思い出すまで、この答えは私を笑わせました)、それをプロジェクトに取り入れようとしています。現在取り組んでいます。簡潔な質問は最後に選択されますが、一般的に、作業コードに前方宣言が完全にないことに混乱しています。

すべてのクラスは (サブ) フォルダーによって分離され、それぞれが個別の.hおよび.cppファイルに分けられますが、依存関係について理解するにはこれで十分なはずです。

// FE.h - no implementations - no .cpp file
class FE
{
    private:
       virtual void somePrivateFunc() = 0;
    // 90% virtual class, interface for further implementations
    friend class TLS;
};

// DummyFE.h
#include "FE.h"
class DummyFE :: public FE {
    /* singleton dummy */
    private:
        // constructor
    public:
        static DummyFE& instance();
};
// DummyFE.cpp
#include "DummyFE.h"
// all Dummy FE implementation

// ImplFE.h
#include "FE.h"
class ImplFE :: public FE { /* implemented */ };
// ImplFE.cpp
#include "FE.cpp"
// all Impl FE implementations


// SD.h - implements strategy design pattern
//        (real project has more than just FE class in here)
#include "FE.h"
#include "DummyFE.h"
class SD
{
    private:
        FE &localFE;
    public:
        SD(FE &paramFE = DummyFE::instance());
    // ... and all the other phun stuff ... 
    friend class TLS;
};
// SD.cpp - implementations
# include "SD.h"
/* SD implemented */

// TLS.h - implements strategy design pattern
           (on a higher level)
#include SD.h
class TLS{
    private:
        SD *subStrategy;
    public:
        void someFunctionRequiringFriendliness();
}

// TLS.cpp - implementations
#include "TLS.h"
void TLS::someFunctionRequiringFriendliness(){
    this->subStrategy->localFE.somePrivateFunc(); // ok!
}

さて、私はこれをすべて実際にすべての依存関係でコンパイルするパーティーを開催しました (それを機能させるには、最終的にクラス図に書き留める必要がありました) が、今ではそうです。実際に私を混乱させているのは、前方宣言が必要ないということです。以前から前方宣言について知っていたので、念のため、この答えで記憶をリフレッシュしました。

だから、それを明確にするために、私の質問: をclass TLS友人として宣言するとき、明示的な前方宣言が必要ないのはなぜですか? friend classそれは、宣言がすべてそれ自体の前方宣言であることを意味しますか? 私にとって、直感的に、ここに何かが欠けています...そして、コンパイルして正常に動作するので、誰かが私の直感を修正するのを手伝ってくれますか? :D

PS質問とたくさんのコードの長い紹介で申し訳ありません。私のコードの概念についてコメントしないでください - 友人はここで良いです、私はそれが私の現在のプロジェクトにとって正しいと確信しています (このスケルトンからは少しわかりにくいです)。どこにも前方宣言が必要なかった理由を知りたいだけです。

4

4 に答える 4

7
friend class TLS;

この構文それ自体が宣言であるため、この型の以前の宣言を追加する必要はありません。friend宣言は、 (特に関数の場合)囲んでいる名前空間の宣言とは少し異なることに注意してください。

特に、囲んでいる名前空間にも宣言がない限り、宣言で宣言された関数は、friend引数に依存するルックアップによってのみ見つけることができます(クラスの外部で定義することはできません)。同じことがクラスにも当てはまりますが、名前空間レベルでの宣言がない限り、そのように宣言された型は、フレンドとして宣言しているクラスの外部では使用できません。

class B {
   friend class A;
};
//A foo();    // Error: A is not declared here!
class A;
A foo();      // Fine
于 2012-03-27T13:48:59.660 に答える
7

そうです、friend 宣言は forward 宣言のようなものです。

以下がコンパイルされます。

class A;
class B
{
   friend A;
};

また

class B
{
   friend class A;
};

これはしません:

class B
{
   friend A;
};

friend前方宣言するのは実際には宣言でclass Aはなく、classキーワードです。これが、2 番目の例が機能しない理由Aです。A最初のスニペットのように事前に宣言するAと、クラス宣言に解決できます。

私は訂正します。

于 2012-03-27T13:47:34.420 に答える
3

次のように、前方宣言はファイルの先頭にある必要はありません

class A;
class C;
class D;
class B
{
   A* a;
   C* c;
   D* d;
};

と同じです

class B
{
   class A* a;
   class C* c;
   class D* d;
};

推奨される友人の構文は、後者を使用するだけです

于 2012-03-27T13:56:06.343 に答える
2

それは、フレンド クラスの宣言がすべて前方宣言であることを意味しますか?

はい

于 2012-03-27T13:48:00.473 に答える