Экземпляр частного вложенного класса С++

У меня есть следующий код

class A
{
private:
    class B
    {
    public:
        void f()
        {
            printf("Test");
        }
    };
public:
    B g() 
    {
        return B(); 
    }
};


int main()
{
    A a;
    A::B b; // Compilation error C2248
    A::B b1 = a.g(); //Compilation error C2248
    auto b2 = a.g(); // OK
    a.g(); // OK 
    b2.f(); // OK. Output is "Test"
}

Как вы можете видеть, у меня есть класс A и частный вложенный класс B. Без использования auto я не могу создать экземпляр A:: B вне A, но с авто я могу. Может кто-нибудь объяснить, что здесь не так? Я использую VС++ 12.0, 13.0, 14.0 (всегда такое же поведение)

Ответы

Ответ 1

Тип B доступен только для A и друзей A, что означает, что другой код не может ссылаться на него. С другой стороны, вывод типа шаблона работает даже для частных типов, что необходимо, если вы когда-либо хотели использовать свой частный тип в любой форме шаблона внутри кода A.

Функция auto основана на выводе типа шаблона и соответствует тем же правилам, что и для вызова auto b2 = a.g();.

Ответ 2

Тип вывода!

Когда у вас есть закрытый класс (A::B), встроенный внутри другого класса, только внешний класс может создавать объекты частного типа A::B.

Следующие объявления пытаются создать объект, в котором у вас нет доступа к A::B:

A::B b; // Compilation error C2248
A::B b1 = a.g(); //Compilation error C2248

Это связано с тем, что в функции main() вы не можете "видеть" (или доступ) закрытый класс, скрытый внутри A. auto обходит это. Публичная функция A::g() способна создать экземпляр A::B и вернуть его вам.

auto обходит это, выведя тип позже. Когда компилятор обрабатывает вывод типа auto b2 = a.g();, он обнаружит, что тип A::B. Это нормально, потому что A::g() является функцией-членом A и имеет доступ к A::B.

По существу, только члены A могут объявлять A::B, но A::B может быть выведен через открытый член A, который возвращает A::B.