2009-09-04 4 views
11

함수 내에서 사용 정수 상수를 정의하는 일반적인 방법은 다음C++ 코드에서 하나의 상수를 정의하기 위해 enum을 사용해야하는 이유가 있습니까?

const int NumbeOfElements = 10; 

클래스 내에서 사용하기위한 동일한 :

class Class { 
... 
    static const int NumberOfElements = 10; 
}; 

그것은 다음 고정 크기 어레이로서 사용될 수있다 bound는 컴파일 타임에 알려진 것을 의미합니다.

오래 전에 컴파일러는 후자의 구문을 지원하지 않았고 그 열거 형이 사용 된 이유는 다음과 같습니다

enum NumberOfElementsEnum { NumberOfElements = 10; } 

지금 거의 모든 널리 사용되는 컴파일러 지원과 함께 모두가에서 기능 const int과는 동급 static const int 구문은

이 목적을 위해 열거 형을 사용하는 이유가 있습니까?

답변

23

이유는 주로 간결성입니다. 우선, enum는 익명으로 할 수 있습니다

class foo { 
    enum { bar = 1 }; 
}; 

이 효과적으로 필수적인 상수로 bar을 소개합니다. 위 내용은 static const int보다 짧습니다.

또한 enum 회원 인 경우 누구도 &bar을 쓸 수 없습니다. 당신은이 작업을 수행 할 경우

class foo { 
    static const int bar = 1; 
} 

다음 클래스의 클라이언트가이 수행합니다

printf("%p", &foo::bar); 

그는 (foo::bar가 정의되어 있지 않은 것을 컴파일시 링커 오류가 발생합니다, 때문에 물론, 같은 lvalue, 그렇지 않습니다). 실제적으로, 현재 스탠드 (Standard)가있는 곳에서는 bar이 사용되며, 정수 상수 표현이 이 필요하지 않은 곳에서는이 필요하다.표현식이 필요한 장소는 enum 초기화 자, case 레이블, 배열 크기 (유형은 new[] 제외) 및 정수 유형의 템플릿 인수입니다. 따라서 기술적으로 다른 곳에서는 bar을 사용하면 정의가 필요합니다. 자세한 내용은 C++ Core Language Active Issue 712을 참조하십시오. 아직 제안 된 해결책이 없습니다.

실제로 대부분의 컴파일러는 이와 관련하여 좀 더 관대하며 정의를 요구하지 않고도 대부분의 "상식"을 사용하여 변수 static const int을 사용하지 못하게합니다. 그러나 모퉁이의 경우는 다를 수 있지만 많은 사람들이 익명의 enum을 사용하는 것이 더 좋다고 생각합니다. 모든 것이 명료하고 명확한 모호성은 없습니다.

+1

흠, gcc는 -pedantic -Wall -Wextra를 사용해도이 점에 대해 불평하지 않습니다. 어쨌든 링크 시간까지 오류를 감지 할 수 없기 때문에 짐작할 수 있습니다. 이식성이없는 코드를 진단하려고 시도하는 것을 포기합니다. –

+0

좋은 답변입니다. 명시 적으로 언급하지 않은 또 다른 좋은 점은 열거 형은 rvalue이므로 저장소가 할당되지 않는다는 것입니다. 템플릿 메타 프로그래밍을하고 많은 수의 클래스 템플릿을 인스턴스화하는 경우 컴파일러 최적화에 의존하기보다는 * 확실하게 알 수 있습니다. – jalf

+1

클래스의 외부에'static const int '에 대한 정의가 없다면, 그 클래스에 할당 된 스토리지가 없습니다. 또한 rvalues는 저장소를 할당 할 수 있습니다 (예 : 임시 저장소는 rvalues이고 저장소는 확실히 사용합니다). –

-2

하단 라인 - 사용 const.

자세한 내용 :

은 내가 C++ 전문가가 아니지만, 이것은 일반적인 디자인 질문을 보인다.

필수 항목이 아니며 열거 형이 하나 이상의 값을 갖도록 성장할 확률이 매우 낮거나 존재하지 않는다고 생각되면 정규 const를 사용하십시오. 비록 당신이 틀렸고 미래의 어느 시점에 더 많은 가치가있을지라도 열거 형을 올바른 선택으로 만드는 것입니다 - 간단한 리펙토링과 const를 enum으로 바꿉니다.

+0

상위 수준의 설계 관점에서 볼 때'enum'과'const'에 관한 것이 아닙니다. 이것은 각 구조와 관련된 C++의 단점에 관한 것입니다. 분명한 대답은 여기에 잘못되었습니다. –

3

열거 형을 사용할 이유가 없으며 열거 형은 암시 적으로 정수로 변환 할 수있는 경우에도 열거 형을 사용하기 때문에이 목적으로 static const int을 사용하는 것이 실제로 더 효과적이라고 생각합니다.

+0

나는 downvoted되는 것이 신경 쓰이지 만, 이유를 알려주는 것이 좋을 것이다. 감사. –

+3

열거 형에 고유 한 형식이있는 것이 나쁜 이유는 무엇입니까? 귀하의 프로그램에는 초과 할 수없는 유형 할당량이 있습니까? –

+0

@Rob Kennedy와 동의합니다. 상수의 강력한 타이핑은 열거 형의 ** 포인트 **입니다. –

9

클래스 정의에서 직접 정적 상수를 정의하는 것은 C++에 대한 추후 추가 사항이며 그 중 많은 것은 여전히 ​​enum을 사용하는 이전 해결 방법을 고수하고 있습니다. 클래스 정의에서 직접 정의 된 정적 상수를 지원하지 않는 오래된 컴파일러가 여전히 사용 중일 수도 있습니다.

+2

일부 컴파일러는 항상 정적 const int를 인라인하지 않지만 enum은 항상 AFAIK 인라인됩니다. –

5

귀하의 경우에도 상수를 사용합니다. 그러나 다른 어떤 경우, 내가 다른 관련 상수를 추가 할 수도 있습니다. 이처럼 : 이러한 경우

const int TextFile = 1; // XXX Maybe add other constants for binary files etc.? 

,이 같은 단일 값으로 바로 열거를 사용

enum FileType { 
    TextFile = 1 
    // XXX Maybe add other values for binary files etc.? 
} 

이유는 컴파일러가 다음 경고를 발행 할 수 있다는 내가 사용하고 때 에서와 같이 스위치 식의 상수 값 :

나는 (이 예에서는 파일의 다른 유형) 기존 값과 관련된 또 다른 상수 값을 추가하기로 결정 경우
FileType type; 
// ... 
switch (type) { 
    case TextFile: 
     // ... 
} 

, 거의 모든 컴파일러 줘야 switch 문에서 새 값이 처리되지 않으므로 경고를 보냅니다.

대신 'int'및 상수를 사용했다면 컴파일러는 경고를 발행 할 기회가 없습니다.

5

"enum hack"을 사용하는 유일한 이유는 이전 컴파일러가 여러분의 질문에서 말하는 것처럼 클래스 내 const 정의를 지원하지 않는다는 것입니다.따라서 코드가 이전 컴파일러로 이식 될 것으로 의심되는 경우가 아니라면 const가 필요한 곳에 const를 사용해야합니다.

1

글쎄, 이식성이 인 경우에는 열거 형을 사용하는 데는 충분한 이유가입니다. 컴파일러가 "static const int S = 10"을 지원하는지 여부를 걱정할 필요가 없기 때문에 위대합니다.

또한, 정적 변수는 어딘가에서 정의되어야합니다. enum 값은 선언 된 대로만 사용해야합니다.

+0

선언에 정수 상수 표현식 이니셜 라이저가 포함되어 있으면 정수형의 '정적 const'값을 정의 할 필요는 없지만 그 규칙은 매우 흐립니다. 내 대답을 보라. –

5

enum의 사용에는 장점이 있습니다. 만약 예를 들어, 정의하면 있도록 열거 타입은 타입 :

enum EnumType { EnumValue1 = 10, EnumValue2 = 20 ... }; 

하면 같은 함수가 : 당신이 열거 EnumType의 부재를 전달하는

void Function1(EnumType Value) 

컴파일러 점검 함수이므로 매개 변수 값에 유효한 값만 EnumValue1 및 EnumValue2가됩니다. 는 상수를 사용

void Function1(int Value) 

로 함수에 INT (INT 어떤 상수, 변수 또는 문자)를 전달하는 컴파일러 검사 기능을 변경합니다.

관련 형식은 관련 const 값을 그룹화하는 데 적합합니다. 단 하나의 const 값으로는 어떤 이점도 보이지 않습니다.

2

둘 사이에는 차이가 있습니다. Enum에는 내가 아는 한 주소가 없습니다. 정적 const int하지만 할. 따라서 누군가가 const static int의 주소를 가져 와서 const를 제거하면 값을 수정할 수 있습니다 (컴파일러는 const로 생각하기 때문에 변경 사항을 무시할 수 있음). 물론 이것은 순수한 악이며 컴파일러는이를 막을 수 없습니다. 열거 형에서는 이런 일이 발생할 수 없습니다.

그리고 만약 당신이 (어떤 이유로) 그 const의 주소가 필요하다면 static const int가 필요합니다.

짧은 열거 형은 rvalue이며 const static int는 lvalue입니다. 자세한 내용은 http://www.embedded.com/story/OEG20011129S0065을 참조하십시오.

+0

클라이언트는 'static const int'멤버 변수의 주소를 정의없이 취할 수 없습니다. 그래도 Rvalue/lvalue 구별이 중요합니다. –

+0

클라이언트는 그렇지 않지만 나중에 클래스를 유지 관리하고 코드를 추가하는 사람은 없습니다. –

관련 문제