static
members
클래스 정의 내부에서, 키워드 static 는 클래스 인스턴스에 바인딩되지 않는 멤버들을 선언합니다.
클래스 정의 외부에서는 다른 의미를 가집니다: storage duration 을 참조하십시오.
목차 |
구문
정적 멤버에 대한 선언은 멤버 선언 으로서, 선언 지정자에 static 키워드를 포함합니다. static 키워드는 일반적으로 다른 지정자 앞에 나타나며 (이 때문에 구문이 비공식적으로 static data-member 또는 static member-function 으로 설명됩니다), 하지만 지정자 시퀀스의 어느 위치에도 나타날 수 있습니다.
모든 정적 데이터 멤버와 정적 멤버 함수의 이름은 이를 포함하는 클래스의 이름과 달라야 합니다.
설명
클래스의 정적 멤버들은 클래스 객체와 연관되지 않습니다: 이들은 정적 또는 스레드 (since C++11) storage duration 을 가지는 독립 변수이거나 일반 함수입니다.
static 키워드는 클래스 정의 내부에서 static 멤버의 선언에만 사용되며, 해당 static 멤버의 정의에는 사용되지 않습니다:
class X { static int n; }; // 선언 ('static' 사용) int X::n = 1; // 정의 ('static' 사용하지 않음)
클래스 본문 내의 선언은 정의가 아니며, 멤버를 불완전한 타입 ( void 제외)으로 선언할 수 있으며, 여기에는 해당 멤버가 선언된 타입 자체도 포함됩니다:
struct Foo; struct S { static int a[]; // 선언, 불완전 타입 static Foo x; // 선언, 불완전 타입 static S s; // 선언, 불완전 타입 (자체 정의 내부) }; int S::a[10]; // 정의, 완전 타입 struct Foo {}; Foo S::x; // 정의, 완전 타입 S S::s; // 정의, 완전 타입
|
그러나 선언이 constexpr 또는 inline (C++17부터) 지정자를 사용하는 경우, 해당 멤버는 완전한 타입으로 선언되어야 합니다. |
(C++11부터) |
클래스
T
의 정적 멤버
m
를 참조하기 위해 두 가지 형식을 사용할 수 있습니다: 한정된 이름
T::m
또는 멤버 접근 표현식
E.m
또는
E->m
, 여기서
E
는 각각
T
또는
T*
로 평가되는 표현식입니다. 동일한 클래스 범위 내에서는 한정이 불필요합니다:
struct X { static void f(); // 선언 static int n; // 선언 }; X g() { return X(); } // X를 반환하는 함수 void f() { X::f(); // X::f는 정적 멤버 함수의 한정된 이름 g().f(); // g().f는 정적 멤버 함수를 참조하는 멤버 접근 표현식 } int X::n = 7; // 정의 void X::f() // 정의 { n = 1; // X::n은 이 스코프에서 단순히 n으로 접근 가능 }
정적 멤버는 클래스 멤버 접근 규칙(private, protected, public) 을 따릅니다.
정적 멤버 함수
정적 멤버 함수는 어떤 객체와도 연관되지 않습니다. 호출될 때, 이들은 this 포인터를 가지지 않습니다.
정적 멤버 함수는 virtual , const , volatile , 또는 ref-qualified 로 선언될 수 없습니다.
정적 멤버 함수의 주소는 일반적인 함수 포인터 에 저장될 수 있지만, 멤버 함수 포인터 에는 저장될 수 없습니다.
정적 데이터 멤버
정적 데이터 멤버는 어떤 객체와도 연관되지 않습니다. 클래스의 객체가 정의되지 않더라도 존재합니다. 정적 데이터 멤버의 인스턴스는 전체 프로그램에서 오직 하나만 존재하며 정적 storage duration 을 가지며, thread_local 키워드가 사용된 경우에는 스레드당 하나의 객체가 thread storage duration을 가집니다 (since C++11) .
정적 데이터 멤버는 mutable 로 선언될 수 없습니다.
네임스페이스 범위에 있는 클래스의 정적 데이터 멤버는 외부 링크 를 가지며, 이는 클래스 자체가 외부 링크를 가질 경우(즉, 무명 네임스페이스 의 멤버가 아닐 경우)에 해당합니다. 지역 클래스(함수 내부에 정의된 클래스)와 무명 클래스, 그리고 무명 클래스의 멤버 클래스를 포함한 이러한 클래스들은 정적 데이터 멤버를 가질 수 없습니다.
|
정적 데이터 멤버는 inline 으로 선언될 수 있습니다. 인라인 정적 데이터 멤버는 클래스 정의 내에서 정의될 수 있으며 초기화자를 지정할 수 있습니다. 클래스 외부 정의가 필요하지 않습니다: struct X { inline static int fully_usable = 1; // No out-of-class definition required, ODR-usable inline static const std::string class_name{"X"}; // Likewise static const int non_addressable = 1; // C.f. non-inline constants, usable // for its value, but not ODR-usable // static const std::string class_name{"X"}; // Non-integral declaration of this // form is disallowed entirely }; |
(C++17부터) |
상수 정적 멤버
정수형이나 열거형의 정적 데이터 멤버가 const (그리고 volatile 가 아닌)로 선언된 경우, 모든 표현식이 초기화 에서 상수 표현식 인 이니셜라이저를 사용하여 클래스 정의 내부에서 직접 초기화될 수 있습니다:
struct X { const static int n = 1; const static int m{2}; // C++11부터 const static int k; }; const int X::k = 3;
|
LiteralType 의 정적 데이터 멤버가 constexpr 로 선언된 경우, 모든 표현식이 상수 표현식인 초기화자를 사용하여 클래스 정의 내부에서 바로 초기화되어야 합니다: struct X { constexpr static int arr[] = { 1, 2, 3 }; // OK constexpr static std::complex<double> n = {1,2}; // OK constexpr static int k; // Error: constexpr static requires an initializer }; |
(C++11부터) |
const non-inline (since C++17) static 데이터 멤버 또는 constexpr static 데이터 멤버 (since C++11) (until C++17) 가 ODR-use 되는 경우, 네임스페이스 범위에서의 정의가 여전히 필요하지만 초기화자를 가질 수 없습니다.
|
constexpr 정적 데이터 멤버는 암시적으로 inline 이며 네임스페이스 범위에서 재선언할 필요가 없습니다. 초기화자 없이 재선언하는 것(이전에는 필요했음)은 여전히 허용되지만, 사용이 권장되지 않습니다. |
(C++17부터) |
struct X { static const int n = 1; static constexpr int m = 4; }; const int *p = &X::n, *q = &X::m; // X::n과 X::m은 ODR-사용됨 const int X::n; // … 따라서 정의가 필요함 constexpr int X::m; // … (C++17에서는 X::m 제외)
키워드
결함 보고서
다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| CWG 194 | C++98 | (static) 멤버 함수 이름이 클래스 이름과 같을 수 있음 |
명명 제한이 추가됨 (including
non-static member functions ) |
참고문헌
- C++23 표준 (ISO/IEC 14882:2024):
-
- 11.4.9 정적 멤버 [class.static]
- C++20 표준(ISO/IEC 14882:2020):
-
- 11.4.8 정적 멤버 [class.static]
- C++17 표준(ISO/IEC 14882:2017):
-
- 12.2.3 정적 멤버 [class.static]
- C++14 표준(ISO/IEC 14882:2014):
-
- 9.4 정적 멤버 [class.static]
- C++11 표준 (ISO/IEC 14882:2011):
-
- 9.4 정적 멤버 [class.static]
- C++98 표준(ISO/IEC 14882:1998):
-
- 9.4 정적 멤버 [class.static]