본문 바로가기
번역/Bjarne Stroustrup's C++ Style and Technique FAQ

How do i define an in class constant?

by 겜게준 2018. 8. 12.

본문


내부 클래스 상수는 어떻게 정의하나요


상수 표현식에서 사용할 수 있는 상수, 예를들자면 배열 범위를 원한다면, 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"이 이식성있고 내부 클래스 초기화 문법의 비 표준 확장을 사용하는것을 시도하지 못하게 해주기 때문입니다.


그래서 왜 이런 복잡한 제한들이 있는건가요? 클래스는 보통 헤더파일에 선언되고, 헤더파일은 보통 많은 번역 단위[각주:1]에 포함되게 됩니다. 그런데 복잡한 링커 규칙을 피하려면, 모든 객체가 각자 유일한 정의가 있어야 합니다. 이러한 규칙은 객체로 메모리에 적재되어야 하는 엔티티의 내부 클래스 정의를 c++이 허용하는 경우에 깨질것입니다. c++ 디자인의 타협접에 대한 설명을 보려면 D&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

// ...

}

  1. c c++에서 컴파일의 기본 단위입니다. [본문으로]

댓글