12

次のコードを検討してください。

namespace foo {}

class A
{
   class B
   {
   };

   friend int foo::bar( B& );
};

namespace foo
{
   int bar( A::B& )
   {
   }
}

G++ 4.4.3 は私に教えてくれます:

friendfun-innerclass.cpp:21: エラー: 'int foo::bar(A::B&)' は 'foo' 内で宣言されている必要があります

しかし、私は宣言することはできません:

namespace foo
{
   int bar( A::B& );
}

A::B が宣言されていないため、クラス A の定義の前。そして、明らかに「クラス A::B」を宣言することはできません。クラス BI を宣言するには、クラス A の定義を指定する必要があり、私の知る限り、「フレンド」宣言はクラス A の定義内にある必要があります。

私にとって奇妙なのは、関数 "bar()" を名前空間 foo から取り出すと、すべて正常に動作することです。関数が名前空間内にあるか、名前空間内にないかによって、コンパイラがクラス内のフレンド関数宣言を受け入れるかどうかが変わることは、直感に反しているように思えます。

これを機能させるために、すべての宣言などを適切に構造化する方法を知っている人はいますか?

4

5 に答える 5

3

のプロトタイプを提供するために、ネストされたクラスを前方宣言する必要があるため(これはできません)、思い通りにはできませんfoo::bar

この問題を回避するための最初の試みとして、おそらくfoo::bar関数テンプレートを作成することに頼るでしょう。そうすれば、コンパイラは後で型を解決し、既知にAなります。B

テスト ハーネス:

namespace foo
{
    template<class B> int bar(B&);
};

class A
{
   class B
   {
       template<class B> friend int foo::bar( B& );
       int n_;
   public:
       B() : n_(42) {}
   };

public:
    B b_;
};

template<class B> int foo::bar(B& b)
{
    return b.n_;
}

int main()
{
    A a;
    foo::bar(a.b_);
}
于 2011-10-11T15:44:23.487 に答える
0

A::Bの前方宣言を書く方法がないため、それを行うことはできませんfoo(A::B&)

ただし、「フレンド名インジェクション」と呼ばれるトリックを使用して、クラス定義でフレンド関数を宣言 (および場合によっては定義) することができます。bar(b)このようにして、名前空間修飾子なしで (たとえばの代わりに)そのフレンド関数を呼び出すことができfoo::bar(b)、引数依存のルックアップは呼び出しを正常に解決します。

struct A
{
    struct B {};

    friend int bar(B&) { // inject bar() into the outer namespace
        // implementation here
    }
};

namespace foo
{
   int foo()
   {
       A::B b;
       return bar(b); // it calls bar(B&) declared in A
   }
}
于 2011-10-11T17:46:37.570 に答える
0

あなたにはそれができないようです。できることは、静的メンバーを持つクラスを前方宣言することであり、クラスは友情を獲得します。しかし、友情を使用するときはいつでも、少なくともデザインをもう一度見て、その理由を自問してください。それは大丈夫かもしれませんし、より良い答えがあるかもしれません。

namespace foo { class bar; }

class A
{
   class B
   {
   };

   friend class ::foo::bar;
};

namespace foo
{
   class bar
   {
   public:
      static int run_bar( A::B& )
      {
      }
   };
}
于 2011-10-11T15:44:50.327 に答える
0

が必要だと思います::foo::bar

于 2011-10-11T15:34:44.757 に答える
0

内部クラスを前方宣言できないため、できません。

これで終わりです。

namespace foo {
    class A_B;
    int bar(A_B &);
}

struct A
{
   class B
   {
   };

   friend int foo :: bar (A_B&);
};

namespace foo
{
   struct A_B : public A :: B {
     // constructors, delegated if you're C++11 :-)
   };

   int bar (A_B &)
   {
   }
}

の非公開性は失われますがA::B、考えてみればそれは理にかなっています。そうでないと実装できませんfoo::bar

于 2011-10-11T15:38:07.420 に答える