делегирование в половые органы

Иногда, понятие 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, Я не могу объявить b в main. Все же я могу назвать методы от Foo::Bar очень хорошо. Какого черта это позволяется? Это было несчастным случаем или дизайном?


О, ожидайте, это поправляется:

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

Даже при том, что мне не разрешают назвать тип Foo::Bar, это работает просто великолепно с auto...


Noah записал:

имена типов, определенные в рамках определения класса, не могут использоваться вне их класса без квалификации.

Только для забавы, вот то, как можно достигнуть тип снаружи:

#include <type_traits>

const Foo some_foo();

typedef typename std::remove_pointer<decltype( some_foo().operator->() )>::type Foo_Bar;
12
задан fredoverflow 1 June 2010 в 19:05
поделиться

3 ответа

Пытаюсь найти что-нибудь в стандарте, которое подробно объясняет это, но я не могу. Единственное, что я могу найти, это 9.9:

Имена типов подчиняются точно таким же правилам области видимости, как и другие имена. В частности, имена типов, определенные в определении класса, не могут использоваться вне своего класса без уточнения.

По сути, имя Foo :: Bar является частным для Foo, а не определение. Таким образом, вы можете использовать Bars вне Foo, вы просто не можете ссылаться на них по типу, поскольку это имя является частным.

Правила поиска по именам для членов также, по-видимому, имеют некоторое влияние на это. Я не вижу ничего, что конкретно ссылается на «вложенный класс», и поэтому им не было бы позволено (если я не могу найти что-либо на самом деле из-за того, что этого нет).

6
ответ дан 2 December 2019 в 22:22
поделиться

Я не могу дать полный ответ, но, возможно, это отправная точка. Спецификация C++ 1998 включает следующий пример кода в параграф 11.3 [class.access] (стр. 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. Хотя это не то же самое, что публикация типа через сигнатуру функции-члена, это похоже.

3
ответ дан 2 December 2019 в 22:22
поделиться

Думаю, это сделано намеренно. Вы не можете явно создать экземпляр Foo :: Bar , но его можно вернуть из функций-членов, а затем передать его другим функциям-членам. Это позволяет скрыть детали реализации вашего класса.

1
ответ дан 2 December 2019 в 22:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: