2011-08-17 3 views
18

일부 정적 데이터 멤버가있는 클래스를 작성했지만 이제는 "정의되지 않은 참조"에 대한 오류가 발생합니다. 왜이 기능이 작동하지 않습니까? 내가 도대체 ​​뭘 잘못하고있는 겁니까?정적 멤버에 대한 정의되지 않은 참조가 있다는 것은 무슨 의미입니까?

(참고 :.. 이것은 Stack Overflow's C++ FAQ에 항목이 될 것을 의미한다이 형태의 FAQ를 제공하는 아이디어를 비판하려면, 다음 the posting on meta that started all this이 할 수있는 장소가 될 것입니다 그 질문에 답변 자주 묻는 질문 아이디어가 처음에서 시작 C++ chatroom, 모니터링, 그래서 당신의 대답은 아이디어를 내놓았다 사람들이 읽을받을 가능성이 높다.) 당신은에 정의 된 정적 멤버를 초기화해야

+0

http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12 – PlasmaHH

답변

26

이를 이해하려면, 당신은 compiling and linking 잘 이해하고 declarations and definitions의 차이점을 가져야한다. 여기

//In header file 
class Example { 
    static bool exampleStaticMember; 
}; 

exampleStaticMember가 선언되었지만 정의되지 않은 :


은 다음 클래스를 생각해 보자. 즉, exampleStaticMember이 주소가 있어야 함을 의미하는 경우 별도의 정의가 있어야합니다. 일반적으로 클래스 정의에서 정적 데이터 멤버 선언은 해당 멤버의 정의입니다.

필수 선언은 일반적으로 클래스 구성원에 대한 다른 정의가 들어있는 cpp 파일에 있습니다. 클래스 정의와 동일한 네임 스페이스에 있어야합니다. 정의는 어떤 CPP 파일에 넣을 수

//In source file: 
//This may optionally have an initialiser (eg "= true") 
bool Example::exampleStaticMember; 

하지만이 One Definition Rule 깰 가능성이있을 것이기 때문에 그것은, 클래스와 헤더에 넣어해서는 안 : 정의는 일반적으로처럼 보인다. 정적 멤버 변수가 CONST 정수 또는 열거 형이면 특별한 경우로

는, 다음 클래스 정의의 initialiser 가질 수있다 :이 경우

//In header file 
class Example { 
    static const int initialised = 15; 
}; 

를 상기 CPP 파일의 정의는 여전히 필요하지만 이니셜 라이저는 사용할 수 없습니다.

상수 표현식에서 이처럼 초기화 된 정적 멤버를 사용할 수 있습니다.

템플릿 템플릿 정적 데이터 멤버

는 일이 약간 다르다. 정적 멤버는 클래스의 나머지와 함께 헤더에 정의되어야한다 : 클래스 템플릿의 정적 데이터 멤버에 대한 하나의 정의 규칙에 고유의 예외가 있기 때문에

//In header file 
template<typename T> 
class Example { 
    static int exampleInt; 
    static T exampleT; 
} 
template<typename T> int Example<T>::exampleInt; 
template<typename T> T Example<T>::exampleT; 

이 작동합니다.static 키워드는 매우 다른 의미를 취할 수있는 클래스 범위에없는 기능과 개체에 적용되는 정적

다른 용도.

함수 범위의 개체에 적용하면 함수를 처음 실행했을 때 초기화 된 개체가 선언되고 함수 호출간에 값이 계속 유지됩니다.

네임 스페이스 범위 (클래스 또는 함수 정의 외부에있는)의 개체 나 함수에 적용하면 internal linkage으로 개체 또는 함수가 선언됩니다. unnamed-namespace이 더 나은 대안을 제공하기 때문에 객체에 대해서는이 사용법이 사용되지 않습니다.

+0

"정적 멤버 변수가 const 정수 또는 열거 형일 경우 특별한 경우로 클래스 정의의 초기화 프로그램 "을 참조하십시오. 여기에 수업 * 선언 *을 의미합니까? –

+0

@SamGoldberg : 아니요. _declaration_이라고 말하면, 앞으로 선언문을 참조 할 것입니다 (예 :'class Example;'). _definition_은 클래스의 멤버를 선언하는 코드를 의미합니다. (예,이 멤버들은 클래스 정의 외부에서 정의 될 수 있지만 여기서는 중요하지 않습니다.) – Mankarse

5

.cpp 파일의 헤더. 예를 들어 :

// foo.h 

class foo { 
    static int X; 
}; 


// foo.cpp 

#include "foo.h" 

int foo::X = 0; 
관련 문제