본문
내부 클래스 상수는 어떻게 정의하나요
상수 표현식에서 사용할 수 있는 상수, 예를들자면 배열 범위를 원한다면, 2가지 선택지가 있습니다.
class X {
static const int c1 = 7;
enum { c2 = 19 };
char v1[c1];
char v2[c2];
// ...
};
얼핏 보기에는, c1의 선언이 깔끔해보이겠지만, 내부 클래서 초기화 문법에서 사용하기 위해서는 상수가 정수형 static const 거나, 상수 표현식으로 초기화된 열거형이어야만 합니다. 이 방법들은 아주 제한적입니다.
class Y {
const int c3 = 7; // error: static 아님
static int c4 = 7; // error: const 아님
static const float c5 = 7; // error: 정수타입이 아님
};
저는 "enum trick"을 사용하는 경항이 있는데 그 이유는 "enum trick"이 이식성있고 내부 클래스 초기화 문법의 비 표준 확장을 사용하는것을 시도하지 못하게 해주기 때문입니다.
그래서 왜 이런 복잡한 제한들이 있는건가요? 클래스는 보통 헤더파일에 선언되고, 헤더파일은 보통 많은 번역 단위에 포함되게 됩니다. 그런데 복잡한 링커 규칙을 피하려면, 모든 객체가 각자 유일한 정의가 있어야 합니다. 이러한 규칙은 객체로 메모리에 적재되어야 하는 엔티티의 내부 클래스 정의를 c++이 허용하는 경우에 깨질것입니다. c++ 디자인의 타협접에 대한 설명을 보려면 1D&E를 참고하세요.
const가 상수표현식 안에서 사용할 필요가 없다면 더욱 유연하게 처리할 수 있습니다.
class Z {
static char* p; // 정의에서 초기화됨
const int i; // 생성자에서 초기화됨
public:
Z(int ii) :i(ii) { }
};
char* Z::p = "hello, there";
static 멤버가 클래스 밖에 정의가 되어있다면 주소값을 가져올 수도 있습니다.
class AE {
// ...
public:
static const int c6 = 7;
static const int c7 = 31;
};
const int AE::c7; // 정의
int f()
{
const int* p1 = &AE::c6; // error: c6이 lvalue가 아님 (주소값은 lvalue만 가능)
const int* p2 = &AE::c7; // ok
// ...
}
원문
How do I define an in-class constant?
If you want a constant that you can use in a constant expression, say as an array bound, you have two choices:
class X {
static const int c1 = 7;
enum { c2 = 19 };
char v1[c1];
char v2[c2];
// ...
};
At first glance, the declaration of c1 seems cleaner, but note that to use that in-class initialization syntax, the constant must be a static const of integral or enumeration type initialized by a constant expression. That's quite restrictive:
class Y {
const int c3 = 7; // error: not static
static int c4 = 7; // error: not const
static const float c5 = 7; // error: not integral
};
I tend to use the "enum trick" because it's portable and doesn't tempt me to use non-standard extensions of the in-class initialization syntax.
So why do these inconvenient restrictions exist? A class is typically declared in a header file and a header file is typically included into many translation units. However, to avoid complicated linker rules, C++ requires that every object has a unique definition. That rule would be broken if C++ allowed in-class definition of entities that needed to be stored in memory as objects. See D&E for an explanation of C++'s design tradeoffs.
You have more flexibility if the const isn't needed for use in a constant expression:
class Z {
static char* p; // initialize in definition
const int i; // initialize in constructor
public:
Z(int ii) :i(ii) { }
};
char* Z::p = "hello, there";
You can take the address of a static member if (and only if) it has an out-of-class definition:
class AE {
// ...
public:
static const int c6 = 7;
static const int c7 = 31;
};
const int AE::c7; // definition
int f()
{
const int* p1 = &AE::c6; // error: c6 not an lvalue
const int* p2 = &AE::c7; // ok
// ...
}
- c c++에서 컴파일의 기본 단위입니다. [본문으로]
'번역 > Bjarne Stroustrup's C++ Style and Technique FAQ' 카테고리의 다른 글
Does "friend" violate encapsulation? (0) | 2018.12.19 |
---|---|
Why isn't the destructor called at the end of scope? (2) | 2018.08.13 |
Why is the size of an empty class not zero? (0) | 2018.05.10 |
Why is "this" not a reference? (0) | 2018.05.10 |
How are C++ objects laid out in memory? (0) | 2018.05.09 |
댓글