2
class A {};

class B : private A {

};

class C : public B {
public:
    void f() {
        A a; // This line causes error, but works when it is in main() function
    }

};

int main()
{
    C c;
    // A a; --> This line works
    return 0;
}

Bこれは個人的に継承することと関係があると思いますがA、指を置くことはできません。

編集:エラーは「クラスAが表示されていません」です。g++でコンパイルされます。

4

2 に答える 2

12

名前の検索は、アクセスチェックとは別のものです。クラスから継承すると、そのクラスの名前が継承するクラスのスコープに挿入されます。そのため、クラスでCは名前を取得しますAが、アクセスできません。


::A a;1つの解決策は、の代わりに書くことですA a;

于 2013-01-31T00:58:47.120 に答える
3

アルフの答えは正しいですが、もう少し明確にすることができると思います(または、もっと混乱するかもしれません)。クラスの名前は、クラス自体のスコープに注入されます。彼が言及しているように、アクセス指定子は、ルックアップが識別子の意味を見つけたにのみチェックされます。質問のコードでは:

class A {};
class B : private A {};
struct C : public B {
    void f() {
        A a; // This line causes error, but works when it is in main() function
    }
};

処理時C::fに、コンパイラは識別子Aを認識し、解決しようとします。のスコープで検索し、C存在しません。階層を上に移動し、 では検出されませんがB、基本型内で検出されますA(検索により非修飾が に解決Aされます::A::A)。このコンテキストでは、識別子は基本クラス B の基本クラス A 内に挿入された名前 A にA解決され、アクセス指定子がチェックされます。コンパイラは、基本クラス Bにアクセスできるかどうかを確認し、次に基本クラス A にアクセスできるかどうかを確認しますが、これは継承のためにアクセスできず、内部のネストされた名前にアクセスできないと不平を言いますprivateAA.

追加の修飾::Aを提供することで、ルックアップを指示しています。この場合、A完全にアクセス可能なグローバル名前空間で型が検出され、コンパイルされます。

于 2013-01-31T02:30:46.563 に答える