클래스 정의에서 정적 const 정수 멤버 정의 static const int N = 10; }; int

내 이해는 C ++에서는 정수 유형 인 한 클래스 내에서 정적 const 멤버를 정의 할 수 있다는 것입니다.

그러면 다음 코드에서 링커 오류가 발생하는 이유는 무엇입니까?

#include <algorithm>
#include <iostream>

class test
{
public:
    static const int N = 10;
};

int main()
{
    std::cout << test::N << "\n";
    std::min(9, test::N);
}

내가 얻는 오류는 다음과 같습니다.

test.cpp:(.text+0x130): undefined reference to `test::N'
collect2: ld returned 1 exit status

흥미롭게도 std :: min에 대한 호출을 주석 처리하면 코드가 잘 컴파일되고 연결됩니다 (이전 행에서도 test :: N이 참조 되었음에도 불구하고).

무슨 일이 일어나고 있는지 아십니까?

내 컴파일러는 Linux에서 gcc 4.4입니다.



답변

내 이해는 C ++에서는 정수 유형 인 한 클래스 내에서 정적 const 멤버를 정의 할 수 있다는 것입니다.

당신은 일종의 맞습니다. 클래스 선언에서 정적 const 정수를 초기화 할 수 있지만 이는 정의가 아닙니다.

http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr038.htm

흥미롭게도 std :: min에 대한 호출을 주석 처리하면 코드가 잘 컴파일되고 연결됩니다 (이전 행에서도 test :: N이 참조 되었음에도 불구하고).

무슨 일이 일어나고 있는지 아십니까?

std :: min은 매개 변수를 const 참조로 사용합니다. 값을 기준으로했다면이 문제는 없지만 참조가 필요하기 때문에 정의도 필요합니다.

다음은 장 / 절입니다.

9.4.2 / 4 – 경우 static데이터 부재이다 const정수 또는 const열거 형 클래스 정의의 선언이 지정 일정한 이니셜 적분 상수 식 (5.19)한다. 이 경우 멤버는 정수 상수 식에 나타날 수 있습니다. 멤버는 프로그램에서 사용되는 경우 네임 스페이스 범위에서 정의되어야하며 네임 스페이스 범위 정의에는 이니셜 라이저가 포함되지 않아야합니다 .

가능한 해결 방법은 Chu의 답변을 참조하십시오.


답변

그의 C ++ FAQ에있는 Bjarne Stroustrup의 예 는 당신이 정확하다고 제안하며 주소를 사용하는 경우에만 정의가 필요합니다.

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
    // ...
}

그는 “정적 멤버의 주소는 클래스 밖의 정의가있는 경우에만 사용할 수 있습니다.” 라고 말합니다 . 그렇지 않으면 작동 할 것을 제안합니다. min 함수가 어떻게 든 뒤에서 주소를 호출 할 수 있습니다.


답변

이를 수행하는 또 다른 방법은 정수 유형의 경우 상수를 클래스에서 열거 형으로 정의하는 것입니다.

class test
{
public:
    enum { N = 10 };
};


답변

단지 int가 아닙니다. 그러나 클래스 선언에서 값을 정의 할 수 없습니다. 당신이 가지고 있다면:

class classname
{
    public:
       static int const N;
}

.h 파일에 다음이 있어야합니다.

int const classname::N = 10;

.cpp 파일에서.


답변

문제를 해결하는 또 다른 방법은 다음과 같습니다.

std::min(9, int(test::N));

(나는 Crazy Eddie의 대답이 문제가 존재하는 이유를 올바르게 설명한다고 생각합니다.)


답변

C ++ 11부터 다음을 사용할 수 있습니다.

static constexpr int N = 10;

이것은 이론적으로 여전히 .cpp 파일에서 상수를 정의해야하지만 그 주소를 사용하지 않는 N한 컴파일러 구현에서 오류가 발생할 가능성은 거의 없습니다.).


답변

C ++에서는 정적 const 멤버를 클래스 내부에 정의 할 수 있습니다.

아니요, 3.1 §2에서는 다음과 같이 말합니다.

선언은 함수의 본문 (8.4)을 지정하지 않고 함수를 선언 하지 않는 한 정의이며 , 외부 지정자 (7.1.1) 또는 연결 사양 (7.5)을 포함하고 이니셜 라이저 나 함수 본문이 없으며 정적 데이터를 선언합니다. 클래스 정의 (9.4) 에서 멤버 , 클래스 이름 선언 (9.1), opaque-enum-declaration (7.2) 또는 typedef 선언 (7.1.3), using-declaration (7.3. 3) 또는 사용 지시문 (7.3.4).