Экземпляр частного вложенного класса С++
У меня есть следующий код
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
.