2015-01-05 6 views
3

개인을 정의하고 공용으로 보호하려고합니다.C++에서 공개적으로 비공개로 정의하십시오.

#define private public 
#define protected public 

C++에서는 안전한가요?

+6

왜 그렇게할까요? 아마도 프로그램의 런타임 동작을 변경하지는 않지만 매우 유용한 컴파일러 진단 기능을 사용할 수 없게 만듭니다. 당신이 그것을하고 싶어하는 코드를 보여주세요! –

+1

http://www.viva64.com/en/b/0146/ –

+2

하지만 재미 있습니다. –

답변

8

아니요, 거의 확실하게 정의되지 않은 동작이 발생합니다.

가입일 n4296 17.6.4.3.1 [macro.names/2 (이하 @ 제임스 통해)

에 나열된 키워드 식별자에 한해서 전적으로 동일하지 #define 또는 #undef 이름 번역 부, 표 2 또는 7.6에 설명 된 속성 토큰에 적용된다.

privatepublic은 키워드입니다.

17.6.4.1/1 [constraints.overview]

이 섹션에서는 C의 +에 대한 제한을 설명합니다 : 당신은 C++ 표준 라이브러리에서 아무것도 사용 경우 단순히 그들 중 하나에 #define을하는 것은 정의되지 않은 동작 입니다 + C++ 표준 라이브러리의 기능을 사용하는 프로그램

17.6.4.3.1의 제한 사항이 적용되지 않는 것 같습니다.

두 가지 다른 정의가있는 동일한 구조를 사용하면 위반이 발생할 수 있습니다. 대부분의 구현에서는 대 private 이외의 두 구조가 동일하지 않을 수도 있지만 표준에서는 그러한 보장을하지 않습니다.

그럼에도 불구하고 가장 일반적인 종류의 UB는 컴파일러가 거의 신경 쓰지 않으므로 '작동합니다.'입니다.

그러나 그것이 '안전함'을 의미하지는 않습니다. 그것은 특정 컴파일러에서 안전 할 수 있습니다 (컴파일러의 문서를 검사하십시오 : 이것은 이상한 보장을 줄 것입니다!). 몇몇 컴파일러 (있는 경우)는 두 가지 다른 정의를 통해 동일한 구조에 액세스하는 경우 위의 작업에 필요한 레이아웃 보장 (및 맹 글링 보장)을 제공합니다. 예를 들어 다른 오류 가능성이 더 먼 경우에도 마찬가지입니다.

많은 컴파일러가 '효과가 있습니다.' 그렇다고해도 안전하지는 않습니다. 다음 컴파일러 버전은 무수히 많은 변화를 일으키고 코드를 어렵게 (또는 쉽게) 중단하여 방법을 감지 할 수 있습니다.

보수가 큰 경우에만이 작업을 수행하십시오.

표준 라이브러리 헤더를 포함하지 않고 두 컴파일 단위에서 정의를 다르게 사용하지 않는 경우 키워드가 정의되지 않은 동작이라는 증거를 찾을 수 없습니다. 따라서 매우 제한된 프로그램에서는 합법적 일 수 있습니다. 실제로 합법적이라 할지라도 합법성이 매우 취약하고 컴파일러가 그런 종류의 언어 남용에 대해 테스트하거나 버그가 생기면주의를 기울이지 않기 때문에 '안전'하지는 않습니다. #define private foo에 의한

정의되지 않은 동작은 얼마나 깨지기 쉬운의 예로서,std 헤더의 #include 전에 일을 제한하지 않는 것.

+0

미안하지만 UB는 무엇을 의미합니까? – user4419862

+0

@ user4419862 '정의되지 않은 동작' – Elemental

+1

@ k크 -이 사건이 UB 인 이유는 무엇이라고 생각합니까? C++ 스펙에서 제안하는 것은 무엇입니까? – Elemental

1

이 작업을하는 데 불법적 인 것은 없습니다. 단지 미친 짓입니다.

당신은 모든 컴파일 단위 (그렇지 않으면 때문에 이름 맹 글링의 실패 링커를 얻을 수 있습니다.

당신이 호기심에서 묻는 경우 다음이 (혼란 경우) 다 완벽하게 합법적이 정의를 사용해야합니다 ++ ; 당신이 생각하기에 이것이 좋은 아이디어라고 생각하기 때문에 묻는다면, 그 모든 성가신 접근 권한을 가지고 있지 않다면 당신은 매우 나쁜 길을 가고 있습니다. 이 정의를 사용하면 연습 된 C++ 프로그래머가 거의 읽을 수없는 코드가됩니다.

+3

표준에 따르면, 그것은 표준 라이브러리의 일부를 사용하는 경우 적어도 정의되지 않은 동작입니다. –

0

액세스 한정자는 f 또는 인간 만이 당신이 실수로 접근하거나 변경하지 말아야 할 방법이나 필드 등을 사용하지 않도록 할 수 있습니다.

새 코드를 작성하면 항상 모든 것을 공개 할 수 있지만 이전 코드에서는 확실히 무언가를 깨뜨릴 수 있습니다. 그것은 효과가 있지만 물론 오류가 발생하기 쉬울 것입니다. 매번 모든 것에 액세스 할 수 있다면 IntelliSense이 무엇을 제안하는지 상상해보십시오. 액세스 한정자는 잘못된 방식으로 사용한 경우 무언가를 손상시킬 수있는 코드를 보호하지 못하지만 IntelliSense은 특정 상황과 관련이있는 멤버 만 표시 할 수 있습니다.

0

구문은 정확하지만 의미가 잘못되었습니다.

그것은 단지 (심지어 간접적으로) 어떤 방법으로하지 않는 번역 단위에서 허용되는
3

는 표준 헤더를 포함하지만, 당신이 경우에 이와 같은 제한이 있습니다

(17.6.4.3. 1) 번역 ​​단위로 #define하지 않는다 또는 키워드에 전적으로 동일한 이름 [...]에 관계없이 그

#undef를, 그것은 좋은 생각이 일반적이다 - 액세스 한정자 주변에 일 처리에 의해 "안전"하지 않습니다 그 단어 자체의 즉각적인 문제를 일으키지 않더라도 단어의 일반적인 의미.
도서관 코드를 사용하는 경우 일반적으로 보호 대상에 대한 적절한 이유가 있습니다.

일시적으로 항목을 공개하려는 경우 테스트 목적으로 클래스의 해당 부분에 대해 특수 조건 매크로를 사용할 수 있습니다.

#if TESTING 
#define PRIVATE_TESTABLE public 
#else 
#define PRIVATE_TESTABLE private 
#endif 

class Foo 
{ 
public: 
    Foo(); 
    void operation(); 
PRIVATE_TESTABLE: 
    int some_internal_operation(); 
private: 
    int some_internal_data; 
}; 
+1

'친구 클래스 Test_Foo;'더 좋을 것이라고 생각합니다. – Jarod42

관련 문제