IT박스

이중 콜론을 사용하여 네임 스페이스에서 클래스를 전달할 수없는 이유는 무엇입니까?

itboxs 2020. 6. 3. 21:51
반응형

이중 콜론을 사용하여 네임 스페이스에서 클래스를 전달할 수없는 이유는 무엇입니까?


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.

참고URL : https://stackoverflow.com/questions/2059665/why-cant-i-forward-declare-a-class-in-a-namespace-using-double-colons

반응형