문제
누구든지 다음 코드가 컴파일하지 않는 이유를 설명 할 수 있습니까? 적어도 G ++ 4.2.4.
그리고 더 흥미로운 점은 멤버를 INT로 캐스팅 할 때 왜 컴파일됩니까?
#include <vector>
class Foo {
public:
static const int MEMBER = 1;
};
int main(){
vector<int> v;
v.push_back( Foo::MEMBER ); // undefined reference to `Foo::MEMBER'
v.push_back( (int) Foo::MEMBER ); // OK
return 0;
}
해결책
실제로 어딘가에 정적 멤버를 정의해야합니다 (클래스 정의 후). 이 시도:
class Foo { /* ... */ };
const int Foo::MEMBER;
int main() { /* ... */ }
정의되지 않은 참조를 제거해야합니다.
다른 팁
새로운 C ++ 기능의 흥미로운 충돌과 당신이하려는 일 때문에 문제가 발생합니다. 먼저, push_back
서명:
void push_back(const T&)
유형의 객체에 대한 참조를 기대하고 있습니다. T
. 기존 초기화 시스템 하에서 그러한 구성원이 존재합니다. 예를 들어 다음 코드는 잘 컴파일됩니다.
#include <vector>
class Foo {
public:
static const int MEMBER;
};
const int Foo::MEMBER = 1;
int main(){
std::vector<int> v;
v.push_back( Foo::MEMBER ); // undefined reference to `Foo::MEMBER'
v.push_back( (int) Foo::MEMBER ); // OK
return 0;
}
그 값이 저장된 실제 객체가 있기 때문입니다. 그러나 위에서와 같이 정적 const 멤버를 지정하는 새로운 방법으로 전환하면 Foo::MEMBER
더 이상 대상이 아닙니다. 그것은 일정하고 다소 비슷합니다.
#define MEMBER 1
그러나 사전 처리기 매크로의 두통이없고 (및 유형 안전성). 즉, 참조를 기대하는 벡터는 벡터를 얻을 수 없습니다.
C ++ 표준에는 정의가 어떻게 든 필요한 경우 정적 Const 멤버에 대한 정의가 필요합니다.
주소가 사용되는 경우 정의가 필요합니다. push_back
Const 참조별로 매개 변수를 가져 오므로 컴파일러에는 멤버의 주소가 필요하므로 네임 스페이스에서이를 정의해야합니다.
상수를 명시 적으로 캐스팅 할 때, 당신은 임시를 만들고 있으며,이 임시는 참조에 묶여 있습니다 (표준의 특별 규칙에 따라).
이것은 정말 흥미로운 경우이며, 실제로 STD가 귀하의 지속적인 멤버와 동일한 동작을 갖도록 변경되도록 문제를 제기 할 가치가 있다고 생각합니다!
그러나 이상한 방식으로 이것은 단지 '+'연산자의 합법적 인 사용으로 볼 수 있습니다. 기본적으로 unary +
RValue이므로 Const 참조에 대한 RValues의 바인딩 규칙이 적용되므로 정적 Const 멤버의 주소를 사용하지 않습니다.
v.push_back( +Foo::MEMBER );
aaa.h
class Aaa {
protected:
static Aaa *defaultAaa;
};
AAA.CPP
// You must define an actual variable in your program for the static members of the classes
static Aaa *Aaa::defaultAaa;
캐스트가 왜 작동하는지 모르겠지만 Foo :: 회원은 처음으로로드 될 때까지 할당되지 않으며, 절대로드하지 않기 때문에 결코 할당되지 않습니다. 어딘가에 푸에 대한 언급이 있다면 아마도 효과가있을 것입니다.
두 번째 질문과 관련하여 : Push_Ref는 매개 변수로 참조를 취하며 클래스/구조물의 정적 const memeber를 참조 할 수 없습니다. static_cast를 호출하면 임시 변수가 생성됩니다. 이 객체에 대한 언급은 전달 될 수 있으며 모든 것이 잘 작동합니다.
아니면 적어도 이것을 해결 한 내 동료가 그렇게 말했습니다.
C ++ 11에서는 위의 것이 기본 유형에 대해
class Foo {
public:
static constexpr int MEMBER = 1;
};
그만큼 constexpr
부분은 정적을 만듭니다 표현 정적과는 반대로 변하기 쉬운 - 그리고 그것은 매우 간단한 인라인 메소드 정의처럼 동작합니다. 그러나이 접근법은 템플릿 클래스 내부의 C-String ConstexPrs에서 약간 흔들렸다.