12

ときどき、C++ のプライバシーの概念に当惑することがあります :-)

class Foo
{
    struct Bar;
    Bar* p;

public:

    Bar* operator->() const
    {
        return p;
    }
};

struct Foo::Bar
{
    void baz()
    {
        std::cout << "inside baz\n";
    }
};

int main()
{
    Foo::Bar b;   // error: 'struct Foo::Bar' is private within this context

    Foo f;
    f->baz();     // fine
}

Foo::Barですので、privateでは宣言できません。それでも、問題なくメソッドを呼び出すことができます。なんでこんなの許されるの?それは偶然ですか、それとも意図的なものですか?bmainFoo::Bar


ちょっと待ってください。

Foo f;
auto x = f.operator->();   // :-)
x->baz();

type に名前を付けることは許可されていませんが、 ...Foo::Barで問題なく動作します。auto


ノアは次のように書いています。

クラス定義内で定義された型名は、修飾せずにクラス外で使用することはできません。

楽しみのために、外部から型を取得する方法を次に示します。

#include <type_traits>

const Foo some_foo();

typedef typename std::remove_pointer<decltype( some_foo().operator->() )>::type Foo_Bar;
4

3 に答える 3

6

それを詳細に説明する標準の何かを見つけようとしていますが、できません。私が見つけることができる唯一のものは9.9です:

型名は、他の名前とまったく同じスコープ規則に従います。特に、クラス定義内で定義された型名は、修飾せずにクラス外で使用することはできません。

基本的に、Foo::Barの名前は、定義ではなく、Foo にプライベートです。したがって、Foo の外でバーを使用できますが、その名前は非公開であるため、タイプでそれらを参照することはできません。

メンバーの名前検索ルールもこれに何らかの影響を与えるようです。「ネストされたクラス」を具体的に参照するものは何も表示されないため、許可されません(実際に何も見つからないのは、そこにないためです)。

于 2010-06-01T18:49:21.130 に答える
3

完全な答えを提供することはできませんが、おそらく出発点です。C++ 1998 仕様には、段落 11.3 [class.access](p. 175)の下に次のコード例が含まれています。

class A
{
    class B { };
public:
    typedef B BB;
};

void f()
{
    A::BB x;   // OK, typedef name A::BB is public
    A::B y;    // access error, A::B is private
}

この例では、プライベート タイプはパブリックを通じて「公開」されtypedefます。メンバー関数シグネチャを介して型を発行することと同じではありませんが、似ています。

于 2010-06-01T18:53:10.620 に答える
1

これは設計によるものだと思います。のインスタンスを明示的に作成することはできませんFoo::Barが、メンバー関数から返すことができ、それを他のメンバー関数に渡すことができます。これにより、クラスの実装の詳細を隠すことができます。

于 2010-06-01T19:32:12.210 に答える