2014-02-28 2 views
7

g ++에서 매우 예외적 인 오류가 발생했습니다. 유형 별칭이 비공개임을 주장합니다. 내 코드를 줄일 수 시간 후, 나는 다음과 같은 최소한의 테스트 케이스에 도착했습니다 : g ++ 4.8.2와C++ : Strange "private"오류입니다.

template <typename Dummy> 
class Test { 
    struct CatDog { 
     static void meow() 
     { 
      CrazyHouse::TheCatDog::meow(); 
     } 

     struct Dog { 
      static void bark(); 
     }; 
    }; 

    struct CrazyHouse { 
     using TheCatDog = CatDog; 

     static void startMadness() 
     { 
      TheCatDog::meow(); 
      TheCatDog::Dog::bark(); 
     } 
    }; 

public: 
    static void init() 
    { 
     CrazyHouse::startMadness(); 
    } 
}; 

int main() 
{ 
    Test<void> t; 
    t.init(); 
} 

오류 :

test.cpp: In instantiation of 'static void Test<Dummy>::CatDog::meow() [with Dummy = void]': 
test.cpp:19:29: required from 'static void Test<Dummy>::CrazyHouse::startMadness() [with Dummy = void]' 
test.cpp:27:34: required from 'static void Test<Dummy>::init() [with Dummy = void]' 
test.cpp:34:12: required from here 
test.cpp:15:33: error: 'using TheCatDog = struct Test<void>::CatDog' is private 
     using TheCatDog = CatDog; 
           ^
test.cpp:6:41: error: within this context 
      CrazyHouse::TheCatDog::meow(); 
             ^

연타 3.4 동일한 코드를 받아들입니다. 여기서 무슨 일이 일어나고있는 거지, 이건 g ++ 버그 야? 다음의 행동

가 발생하는에서 오류를 중지 : 템플릿 클래스에 반대

  • 는, 클래스에 Test 켜기.
  • 함수에서 명령문을 제거하십시오.
  • TheCatDog::Dog::bark();CatDog::Dog::bark();으로 변경하십시오.
  • 클래스를 제거하고 해당 내용을 Test에 병합합니다.
  • 클래스를 제거하고 내용을 Test에 병합하고 TheCatDog 별칭을 Test으로 변경합니다.
+2

대체로 그렇습니다. – Shoe

답변

-1

컴파일러의 동작은 우리가 말하는 C++의 버전에 따라 잘못되었거나 옳은 것으로 간주 될 수 있습니다. clang의 동작은 C++ 11에 대해 말하면 정확하고 C++ 98에 관해서는 잘못된 것 같습니다.

stackoverflow 항목 C++ nested class access은이를 명확히해야합니다.

+0

중첩 된 클래스가 중첩 된 클래스의 개인 멤버에 액세스 할 수 있어야합니다. 예 : http://ideone.com/wFeE37 –

+3

이 접근 기능이 C++ 03과 C 사이에서 변경된 것 같습니다. ++ 11. http://stackoverflow.com/questions/6998369/c-nested-classes-accessibility – sj0h

+0

@ sj0h 링크를 제공해 주셔서 감사합니다. 그것은 행동의 차이를 설명합니다. –

5

CatDog 식별자의 이름 검색은 private이라고 표시된 Test::CatDog을 찾습니다. 액세스는 CrazyHouse에서 수행되며 friendTest이 아닙니다. 따라서 보호 된 회원에 대한 불법적 인 액세스입니다. 그들은 멤버 함수와 같은 방법으로 중첩 된 클래스의 몸에 대한 액세스를 확장하기로 결정하기 때문에 C++ (11) 귀하의 예를 메모 sj0h @으로

는 유효합니다.

C++ 98 : 중첩 클래스의

회원은도 바깥 쪽 클래스에 우정이 부여 된 클래스 나 함수에, 바깥 쪽 클래스의 멤버에 특별한 액세스 할 수 없습니다; 일반적인 액세스 규칙 (11 절)을 준수해야합니다. C++ 11

:

중첩 클래스는 부재하고 등이 다른 부재와 같은 액세스 권한을 갖는다.

는 (회원은 포함하는 클래스의 private 멤버에 액세스 할 권리가 있습니다.)

그러나, 이러한 변화도 버전 4.9의 최신 빌드에 GCC에서 구현 될 나타나지 않습니다. 따라서 안전하려면 friend 선언을 추가하는 것이 좋습니다.friend 배는 중첩 된 회원에 의해 부여 된 액세스 반면에는 이행하지 않기 때문에,이 정확히 C++ (11)의 변화와 같은 일을 수행하지 않는

friend struct CrazyHouse; 

참고 :이 회원의 정의 후 를 이동해야합니다 입니다.