Почему я не могу переадресовать класс объявления в пространстве имен, используя двойные двоеточия?
class Namespace::Class;
Зачем мне это нужно?:
namespace Namespace {
class Class;
}
Используя VС++ 8.0, проблемы компилятора:
ошибка C2653: "Пространство имен": не является именем класса или пространства имен
Я предполагаю, что проблема здесь в том, что компилятор не может определить, является ли Namespace
классом или пространством имен? Но почему это имеет значение, поскольку это просто декларация?
Есть ли другой способ переслать-объявить класс, определенный в каком-либо пространстве имен? Синтаксис выше кажется, что я "повторно открываю" пространство имен и расширяю его определение. Что делать, если Class
на самом деле не определено в Namespace
? Это приведет к ошибке в какой-то момент?
Ответы
Ответ 1
Потому что вы не можете. На языках С++ полностью квалифицированные имена используются только для обозначения существующих (т.е. Ранее объявленных) объектов. Они не могут использоваться для введения новых объектов.
И вы фактически "открываете" пространство имен для объявления новых объектов. Если класс Class
позже определяется как член другого пространства имен - это совершенно другой класс, который не имеет ничего общего с тем, который вы заявили здесь.
Как только вы дойдете до определения заранее объявленного класса, вам больше не нужно "повторно открывать" пространство имен. Вы можете определить его в глобальном пространстве имен (или в любом пространстве имен, охватывающем ваш Namespace
), как
class Namespace::Class {
/* whatever */
};
Поскольку вы ссылаетесь на объект, который уже был объявлен в пространстве имен Namespace
, вы можете использовать квалифицированное имя Namespace::Class
.
Ответ 2
Вы получаете правильные ответы, позвольте мне просто повторить формулировку:
class Namespace::Class;
Почему я должен это делать?
Вы должны сделать это, потому что термин Namespace::Class
сообщает компилятору:
... ОК, компилятор. Найдите пространство имен с именем Namespace и внутри которые относятся к классу Class.
Но компилятор не знает, о чем вы говорите, потому что он не знает пространства имен с именем Namespace
. Даже если бы существовало пространство имен с именем Namespace
, как в:
namespace Namespace
{
};
class Namespace::Class;
он все равно не будет работать, потому что вы не можете объявить класс в пространстве имен вне этого пространства имен. Вы должны находиться в пространстве имен.
Таким образом, на самом деле вы можете объявить класс в пространстве имен. Просто сделайте следующее:
namespace Namespace
{
class Class;
};
Ответ 3
Я полагаю, что по той же причине вы не можете объявить вложенные пространства имен в один ход следующим образом:
namespace Company::Communications::Sockets {
}
и вы должны сделать это:
namespace Company {
namespace Communications {
namespace Sockets {
}
}
}
Ответ 4
Здесь есть много отличных ответов на вопрос о том, что было причиной отказа от него. Я просто хочу предоставить скучную стандартную статью, которая специально запрещает ее. Это справедливо для С++ 17 (n4659).
Этот параграф [class.name]/2:
Объявление, состоящее исключительно из идентификатора ключа класса; является либо переоформление имени в текущем поле или вперед объявление идентификатора в качестве имени класса. Он вводит класс name в текущую область.
Приведенное выше определяет, что представляет собой форвардное объявление (или redclaration класса). По существу, он должен быть одним из class identifier;
, struct identifier;
или union identifier;
, где идентификатор является общим лексическим определением в [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
Что представляет собой создание общей схемы [a-zA-Z_][a-zA-Z0-9_]*
, с которой мы все знакомы. Как вы можете видеть, это исключает class foo::bar;
из действительного объявления forward, потому что foo::bar
не является идентификатором. Это полное имя, что-то другое.