C++ 열거형이 컴파일러에서 제대로 인식되지 않습니다.
-
22-08-2019 - |
문제
다음 코드가 g++ (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-49)에서 컴파일되지 않는 이유를 설명할 수 있는 사람이 있습니까?
struct X {
public:
enum State { A, B, C };
X(State s) {}
};
int main()
{
X(X::A);
}
내가 받는 메시지는 다음과 같습니다.
jjj.cpp:함수 'int main()'에서:
jjj.cpp:10:'X X::A'는 'struct X'의 정적 멤버가 아닙니다.
jjj.cpp:10:'X::X()' 호출에 일치하는 함수가 없습니다.
jjj.cpp:1:후보자는 다음과 같습니다X::X(상수 X&)
jjj.cpp:5:X::X(X::상태)`
이것은 잘못된 코드입니까, 아니면 컴파일러 버그입니까?
Neil+Konrad가 문제를 해결했습니다.아래 Neil의 답변에 대한 의견을 참조하십시오.
해결책
X(X::A);
ASA 기능 선언이 보이고 있습니다. 이 코드를 정말로 원한다면 다음을 사용하십시오.
(X)(X::A);
다른 팁
정의에서 변수 이름을 잊어 버렸습니다.
int main()
{
X my_x(X::A);
}
귀하의 코드는 구문 적으로이를 함수 선언과 구별 할 수 없기 때문에 컴파일러를 혼동합니다 (반환 X
그리고 통과 X::A
논쟁으로). 의심스러운 경우, C ++ 컴파일러는 항상 선언에 찬성하여 명백합니다.
해결책은 주위에 중복 괄호를 도입하는 것입니다 X
컴파일러는 유형 주위에 괄호를 금지하기 때문에 (Constructo 호출 등과 반대로) :
(X(X::A));
무슨 일이 일어나는지 명확하게 하기 위해서입니다.이 예를 보세요
int main() {
float a = 0;
{
int(a); // no-op?
a = 1;
}
cout << a;
}
무엇을 출력할까요?자, 출력됩니다 0
.그만큼 int(a)
위의 내용은 두 가지 다른 방식으로 구문 분석될 수 있습니다.
- int로 캐스팅하고 결과를 폐기합니다.
- 라는 변수를 선언합니다.
a
.그러나 식별자 주위의 괄호는 무시하십시오.
함수 스타일의 캐스트가 명령문에 사용되고 선언처럼 보이는 상황이 나타나면 컴파일러는 항상 이를 선언으로 간주합니다.구문상 선언이 될 수 없는 경우(컴파일러는 이를 결정하기 위해 전체 줄을 확인합니다) 표현식으로 간주됩니다.따라서 우리는 내부에 할당하고 있습니다 a
위, 외부를 떠나 a
0에.
자, 당신의 경우가 바로 그것입니다.(우연히)라는 식별자를 선언하려고 합니다. A
라는 클래스 내에서 X
:
X (X::A); // parsed as X X::A;
그런 다음 컴파일러는 선언되지 않은 기본 생성자에 대해 불평합니다. 왜냐하면 정적이 가정된 대로 기본 생성자이기 때문입니다.그러나 X에 대한 기본 생성자가 있더라도 물론 여전히 잘못된 것입니다. A
X의 정적 멤버이거나 X의 정적 멤버를 블록 범위에서 정의/선언할 수 없습니다.
넌 할 수있어 ~ 아니다 여러 가지 작업을 수행하여 선언처럼 보입니다.첫째, 전체 표현식을 paren하여 더 이상 선언처럼 보이지 않게 할 수 있습니다.아니면 캐스팅되는 유형을 paren으로 지정하세요.이 두 가지 명확성은 다른 답변에서 언급되었습니다.
(X(X::A)); (X)(X::A)
실제로 개체를 선언하려고 하면 비슷하지만 뚜렷한 모호성이 있습니다.이 예를 보세요:
int main() {
float a = 0;
int b(int(a)); // object or function?
}
왜냐하면 int(a)
다음과 같은 매개변수의 선언일 수 있습니다. a
float 변수를 int로 명시적으로 변환(캐스트)하면 컴파일러는 이것이 선언이라고 다시 결정합니다.그래서 우리는 우연히 다음과 같은 함수를 선언하게 되었습니다. b
, 정수 인수를 사용하여 정수를 반환합니다.위의 명확성을 기반으로 이를 명확하게 하는 방법에는 여러 가지 가능성이 있습니다.
int b((int(a))); int b((int)a);
대상을 그대로 선언해야합니다
X x(X::A);
코드의 버그.
이 두 줄 중 하나는 나에게 효과가 있습니다.
X obj(X::A);
X obj2 = X(X::A);
Neil Butterworth가 지적했듯이 X(X::A)
기능 선언으로 취급되고 있습니다. 익명의 대상을 정말로 원한다면 (X)(X::A)
X 객체를 구성하고 즉시 삭제합니다.
물론 다음과 같은 일을 할 수 있습니다.
int main()
{
// code
{
X temp(X::A);
}
// more code
}
이것은 더 읽기 쉽고 기본적으로 동일한 효과를 갖습니다.