2012-11-23 2 views
118

나는 다음과 같은 코드는 컴파일 및 실행 (vc2012 & gcc4.7.2)비공개 형식으로 자동을 사용할 수있는 이유는 무엇입니까?

class Foo { 
    struct Bar { int i; }; 
public: 
    Bar Baz() { return Bar(); } 
}; 

int main() { 
    Foo f; 
    // Foo::Bar b = f.Baz(); // error 
    auto b = f.Baz();   // ok 
    std::cout << b.i; 
} 

가이 코드는 잘 컴파일하는 것이 올바른지 어떻게 든 놀랐다? 그리고 그것이 왜 정확합니까? 개인 이름으로 auto을 사용할 수 있습니까? (예상대로) 이름을 사용할 수없는 이유는 무엇입니까?

+10

'표준이기 때문에'f.Baz() i'가도 OK 것을 관찰 :: cout << typeid (f.Baz()) .name()'. 클래스 외부의 코드는'Baz()'에 의해 반환 된 타입을 "볼 수"있습니다.이 타입을 붙잡을 수 있다면 이름을 붙일 수 없습니다. –

+2

그리고 그게 이상하다고 생각하면 (당신이 그걸 물어 보는 것처럼 보일 수도 있습니다) 당신이 유일한 전략은 아닙니다;)이 전략은 [Safe-Bool Idiom] (http : // www .artima.com/cppsource/safebool.html). –

+2

기억해야 할 것은 컴파일러가 도움을 줄 수있는 방식으로 API를 설명하는 편의를 위해 'private'이 있다는 것입니다. 'Foo' 사용자가'Bar' 타입에 접근하는 것을 막기위한 것이 아니기 때문에,'Bar'의 인스턴스를 돌려줌으로써'Foo'를 어떤 식 으로든 방해하지 않습니다. –

답변

100

auto에 대한 규칙은 대부분 템플릿 유형 공제와 동일합니다. 당신이 템플릿 함수에 개인 유형의 객체를 전달할 수 같은 이유에 대한 예를 게시 작품 :

template <typename T> 
void fun(T t) {} 

int main() { 
    Foo f; 
    fun(f.Baz());   // ok 
} 

그리고 우리는 템플릿 함수에 개인 유형의 객체를 전달할 수있는 이유, 당신이 물어? 유형의 이름에만 액세스 할 수 없기 때문입니다. 형식 자체는 여전히 유용하므로 클라이언트 코드로 반환 할 수 있습니다.

+25

그리고 * name *의 프라이버시가 * type *과 아무런 관계가 없다는 것을보기 위해서'public : typedef Bar return_type_from_Baz; '를 질문의'Foo' 클래스에 추가하십시오. 이제 형식은 클래스의 개인 섹션에 정의되어 있음에도 불구하고 공용 이름으로 식별 할 수 있습니다. –

+1

@ Steve의 요점을 되풀이하자면 _name_에 대한 액세스 지정자는 'private : typedef Bar return_type_from_Baz;'를 'Foo'에 [demonstosed] (http://ideone.com)을 추가하여 볼 수있는 _type_과는 아무런 관련이 없습니다./iKv2bQ). 'typedef'd 식별자는 액세스 지정자 (public 및 private)를 무시합니다. – damienh

+0

이것은 나에게 의미가 없습니다. 형식의 _name_은 실제 형식의 별칭 일뿐입니다. 내가 'Bar'또는 'SomeDeducedType'이라고 부르는 것은 무엇이 중요합니까? 'class Foo' 나 그 밖의 것들의 사적인 멤버들에게 접근 할 때 사용하는 것과 같지 않습니다. – einpoklum

98

이름이 인 액세스 제어가 적용됩니다. 표준에서이 예에 비교 :

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 
} 
5

다른 (좋은) 답변에 추가하려면, 여기에 문제가 정말로

에서 auto로 할 필요가 없다는 설명 C++ 98에서 예입니다
class Foo { 
    struct Bar { int i; }; 
public: 
    Bar Baz() { return Bar(); } 
    void Qaz(Bar) {} 
}; 

int main() { 
    Foo f; 
    f.Qaz(f.Baz()); // Ok 
    // Foo::Bar x = f.Baz(); 
    // f.Qaz(x); 
    // Error: error: ‘struct Foo::Bar’ is private 
} 

전용 유형을 사용하는 것이 금지되어 있지는 않습니다. 유형을 명명하는 것이 었습니다. 예를 들어 모든 버전의 C++에서 해당 유형의 이름이없는 임시 이름을 만들면 좋습니다.

8

이 질문은 이미 냉기와 R. Martinho Fernandes에 의해 매우 잘 답변되었습니다.

나는 그냥 해리 포터 비유와 질문에 대답이 기회를 놓칠 수있다 :.

class Wizard 
{ 
private: 
    class LordVoldemort 
    { 
     void avada_kedavra() 
     { 
      // scary stuff 
     } 
    }; 
public: 
    using HeWhoMustNotBeNamed = LordVoldemort; 
}; 

int main() 
{ 
    Wizard::HeWhoMustNotBeNamed tom; // OK 
    Wizard::LordVoldemort not_allowed; // Not OK 
    return 0; 
} 
+4

'친구 클래스 Harry;'가 없습니까? – Quentin

관련 문제