이중 콜론을 사용하여 네임 스페이스에서 클래스를 전달할 수없는 이유는 무엇입니까?
class Namespace::Class;
왜 이렇게해야합니까? :
namespace Namespace {
class Class;
}
컴파일러는 VC ++ 8.0을 사용하여 다음을 발행합니다.
오류 C2653 : 'Namespace': 클래스 또는 네임 스페이스 이름이 아닙니다.
여기서 문제는 컴파일러 Namespace
가 클래스인지 네임 스페이스 인지 알 수 없다는 것입니다 . 그러나 왜 이것이 전진 선언이기 때문에 이것이 중요합니까?
네임 스페이스에 정의 된 클래스를 전달하는 다른 방법이 있습니까? 위의 구문은 네임 스페이스를 "다시 열고"정의를 확장 한 것 같습니다. Class
실제로 정의되지 않은 경우 어떻게해야 Namespace
합니까? 이로 인해 어느 시점에서 오류가 발생합니까?
당신이 할 수 없기 때문에. C ++ 언어에서 정규화 된 이름은 기존 (즉, 이전에 선언 된) 엔터티 를 참조하는 데만 사용됩니다 . 새로운 엔터티 를 소개하는 데 사용할 수 없습니다 .
그리고 당신은 있는 새로운 엔티티를 선언하는 네임 스페이스를 "재개"사실. 클래스 Class
가 나중에 다른 네임 스페이스의 멤버로 정의 된 경우 여기에서 선언 한 클래스와 관련이없는 완전히 다른 클래스입니다.
미리 선언 된 클래스 를 정의 할 때 네임 스페이스를 다시 "열지 않아도"됩니다. 전역 네임 스페이스 (또는를 묶는 네임 스페이스 Namespace
)에서 다음과 같이 정의 할 수 있습니다.
class Namespace::Class {
/* whatever */
};
네임 스페이스에서 이미 선언 된 엔터티를 참조하고 Namespace
있으므로 정규화 된 이름을 사용할 수 있습니다 Namespace::Class
.
당신은 정답을 얻고 있습니다, 다시 단어를 써 보도록하겠습니다.
class Namespace::Class;
왜 이렇게해야합니까?
이 용어 Namespace::Class
는 컴파일러에 다음 과 같은 의미를주기 때문에이 작업을 수행해야합니다 .
... OK, 컴파일러. 네임 스페이스라는 네임 스페이스를 찾으십시오.이 네임 스페이스에서 Class라는 클래스를 참조하십시오.
그러나 컴파일러는 네임 스페이스를 모르기 때문에 무슨 말을하는지 알지 못합니다 Namespace
. 다음 Namespace
과 같이 이라는 네임 스페이스가있는 경우에도
namespace Namespace
{
};
class Namespace::Class;
네임 스페이스 외부에서 네임 스페이스 내에 클래스를 선언 할 수 없기 때문에 여전히 작동하지 않습니다. 네임 스페이스에 있어야합니다.
따라서 실제로 네임 스페이스 내에 클래스를 선언 할 수 있습니다. 그냥 이렇게 :
namespace Namespace
{
class Class;
};
중첩 된 네임 스페이스를 한 번에 선언 할 수없는 것과 같은 이유로 다음과 같이 가정합니다.
namespace Company::Communications::Sockets {
}
그리고 당신은 이것을해야합니다 :
namespace Company {
namespace Communications {
namespace Sockets {
}
}
}
전달 선언 변수의 유형이 실제로 무엇인지는 명확하지 않습니다. 앞으로의 선언 class Namespace::Class;
은
namespace Namespace {
class Class;
}
또는
class Namespace {
public:
class Class;
};
그것을 거부하는 데 관련된 이론적 근거에 대한 훌륭한 답변이 많이 있습니다. 나는 단지 지루한 표준 조항을 구체적으로 금지하고 있습니다. 이것은 C ++ 17 (n4659)에서도 마찬가지입니다.
해당 단락은 [class.name] / 2입니다 .
클래스 키 식별자 로만 구성된 선언 ; 현재 범위에서 이름을 다시 선언하거나 식별자를 클래스 이름으로 전달하여 선언 한 것입니다. 클래스 이름을 현재 범위로 소개합니다.
The above defines what constitutes a forward declaration (or redclaration of a class). Essentially, it must be one of class identifier;
, struct identifier;
or union identifier;
where identifer is the common lexical definition in [lex.name]:
identifier: identifier-nondigit identifier identifier-nondigit identifier digit identifier-nondigit: nondigit universal-character-name nondigit: one of a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ digit: one of 0 1 2 3 4 5 6 7 8 9
Which is the production of the common scheme [a-zA-Z_][a-zA-Z0-9_]*
we are all familiar with. As you can see, this precludes class foo::bar;
from being a valid forward declaration, because foo::bar
is not an identifier. It's a fully qualified name, something different.
'IT박스' 카테고리의 다른 글
Kafka를 사용한 데이터 모델링? (0) | 2020.06.04 |
---|---|
특정 행 인덱스에서 데이터 프레임에 새 행을 추가하지 않습니까? (0) | 2020.06.04 |
Maven 프로젝트 버전 상속-상위 버전을 지정해야합니까? (0) | 2020.06.03 |
CSV 데이터에서 MySQL로드 NULL 값 (0) | 2020.06.03 |
자식 커밋을 특정 커밋으로 되돌림 (0) | 2020.06.03 |