私は以下のC ++コードを持っています。
class A {
protected:
struct Nested {
int x;
};
};
class B: public A {
friend class C;
};
class C {
void m1() {
B::Nested n; // or A::Nested
}
};
このスニペットをg ++ 4.4でコンパイルしても、m1でB :: NestedとA :: Nestedのどちらを使用しても違いはありません。 Clangは受け入れます B::Nested
しかし私の場合はコンパイルされません A::Nested
。これはg ++のバグですか、それともclangのバグですか?
回答:
回答№1は8規格によると、GCCは正しく、Clangは間違っています。 11.2 / 4と言っています
メンバmは、クラスNで命名されるとアクセス可能になります。
- Nのメンバーとしてのmは保護されており、参照はクラスNのメンバーまたは友人、またはNから派生したクラスPのメンバーまたは友人の中で行われ、Pのメンバーとしてのmは非公開または保護されています。
これはClangがQtを構築するのを妨げるこのClangバグレポートの主題です。 http://llvm.org/bugs/show_bug.cgi?id=6840 。一人のクランの男が言う
実際、私は意図的に実装していませんまだこの規則。どちらかです 製図ミスまたは恐ろしい間違い。それは全体の「保護された」を否定する 指定子、コードの整形式性を 完全に無関係なクラスが存在すると、コストが高くなります。 そして、それはテンプレートの存在下で正式に決定不可能です。
回答№2の場合は1
C ++では、友達は他動詞ではありません。あなたの友達の友達は必ずしも私の友達とは限りません。
AでNestedを保護することで、すべてのサブクラスはこの要素を使用できますが、それ以外のユーザーはこの要素を使用できません。あなたはこれが一種の友達だと思うかもしれません。 Aは、ネストされた構造体へのアクセスに関してすべてのサブクラスを友達にします。
BはCを友人にしますが、これはCがAの友人でもあるという意味ではありません。したがって、CはNestedにアクセスできません。
しかし:動作がC ++ 03から変更されています。 C ++ 03では、ネストしたクラスはそれを含むクラスのフルメンバーであるため、フルアクセス権があります。友情はまだ推移的ではありませんが、今ではメンバーアクセスはそうです。
あなたが見たいかもしれない http://www.rhinocerus.net/forum/language-c-moderated/578874-friend-transitive-nested-classes.htmlこれも同様の問題を説明しています。