web-dev-qa-db-ja.com

C ++の内部クラスは自動的にフレンドになりますか?

C++で内部クラスを定義すると、それはそれを含むクラスのフレンドになりますか?たとえば、これは合法ですか?

class Outer {
public:
    class Inner {
    public:
        void mutateOuter(Outer& o);
    };

private:
    int value;
};

void Outer::Inner::mutateOuter(Outer& o) {
    o.value ++; // Legal?  Or not?
}

私が試した一部のコンパイラ(VS2003)ではこのコードは機能しないため、私は尋ねますが、少なくとも一部のコンパイラでは機能するという話を聞いています。これについてのC++仕様の関連セクションを見つけることができません。誰かが特定のことを引用できれば、それが合法であるか違法であると言ってもいいでしょう。

69
templatetypedef

多かれ少なかれ同じ質問をした後 ここ 自分自身、C++ 11の(明らかに)更新された回答を共有したいと思いました。

https://stackoverflow.com/a/14759027/1984137 から引用:

標準$ 11.7.1

「ネストされたクラスはメンバーであり、他のメンバーと同じアクセス権を持っています。囲んでいるクラスのメンバーは、ネストされたクラスのメンバーに特別なアクセス権を持ちません。通常のアクセスルールに従います。」

通常のアクセスルールでは、次のように指定されています。

「クラスのメンバーは、クラスがアクセスできるすべての名前にもアクセスできます...」

特定の例が標準で与えられました:

class E {
    int x;
    class B { };

    class I {
        B b; // OK: E::I can access E::B
        int y;
        void f(E* p, int i) {
            p->x = i; // OK: E::I can access E::x
        }
    };
}
65
hcc23

C++ 11まで(つまり、C++ 98およびC++ 03)

C++ 98およびC++ 03では、ネストされたクラスできませんデフォルトで、包含クラスのprivateおよびprotectedメンバーにアクセスします。

C++標準(2003)は$ 11.8/1 [class.access.nest]で述べています、

ネストされたクラスのメンバーは、囲んでいるクラスのメンバーへの特別なアクセス権はありません、および囲んでいるクラスに友情を与えたクラスまたは関数にはアクセスできません。通常のアクセス規則(第11項)に従います。 囲んでいるクラスのメンバーには、ネストされたクラスのメンバーへの特別なアクセス権はありません;通常のアクセス規則(11節)に従う必要があります。

標準自体の例:

class E 
{
    int x;
    class B { };
    class I 
    {
        B b; // error: E::B is private
        int y;
        void f(E* p, int i)
        {
           p->x = i; // error: E::x is private
        }
   };
   int g(I* p)
   {
       return p->y; // error: I::y is private
   }
};

C++ 11以降

上記の制限はC++ 11から削除されました。ネストされたクラスcanは、囲んでいるクラスのprivateおよびprotectedメンバーにアクセスします。

class E 
{
    int x;
    class B { };
    class I 
    {
        B b; // ok: even though E::B is private
        int y;
        void f(E* p, int i)
        {
           p->x = i; // ok: even though E::x is private
        }
   };
   int g(I* p)
   {
       return p->y; // ok: even though I::y is private
   }
};

お役に立てば幸いです。

37
Nawaz

質問者は答えの1つを受け入れたようですので、これは単なる補足です。
規格は、アクセシビリティに関する仕様を変更したようです。

C++ 98の§11.8/ 1は次のように述べています:

ネストされたクラスのメンバーは、囲んでいるクラスのメンバーや、囲んでいるクラスに友情を与えたクラスや関数に特別なアクセス権を持ちません。通常のアクセス規則に従います。

§11.8/ 1(TR1以降)N1804は次のように述べています。

ネストされたクラスはメンバーであり、他のメンバーと同じアクセス権を持っています。

現在のC++コンパイラは新しい仕様に準拠していると思います。

16
Ise Wisteria

この回答は(古い)C++ 03仕様に関連しています。この質問で受け入れられた回答はより最新のものです。

さて、私はこれをカバーする仕様の関連部分を見つけたので、今この質問をするのはばかげています:§11.8/ 1:

ネストされたクラスのメンバーは、囲んでいるクラスのメンバーや、囲んでいるクラスに友情を与えたクラスや関数には特別なアクセス権を持ちません。通常のアクセス規則(11節)に従う必要があります。包含クラスのメンバーは、ネストされたクラスのメンバーに特別なアクセス権を持ちません。通常のアクセス規則(11節)に従う

(私の強調)

そのため、内部クラスには特別なアクセス権限はありません。

4
templatetypedef

頭の上の正確な位置はわかりませんが、仕様を読んで、クラス内のプライベートデータがネストされたクラスを含む他のすべてのクラスから隠されていることを思い出しました。

基本的に、クラスをネストすると、アクセス権ではなく特定のスコープが定義されます。