Почему я не могу переслать-объявить класс в пространстве имен с помощью двойных двоеточий?
class Namespace::Class;
почему я должен это делать?:
namespace Namespace {
class Class;
}
используя VC++ 8.0, компилятор выдает:
ошибка C2653: 'Namespace': это не имя класса или пространства имен
Я предполагаю, что проблема здесь в том, что компилятор не может сказать, является ли Namespace это класс или пространство имен? Но почему это имеет значение, так как это просто прямая декларация?
есть ли другой способ переадресации-объявить класс, определенный в некотором пространстве имен? Этот синтаксис выше кажется, что я "открываю" пространство имен и расширяю его определение. А что если Class фактически не были определены в Namespace? Это приведет к ошибке в какой-то момент?
5 ответов:
потому что ты не можешь. В языке C++ полностью квалифицированные имена используются только для обозначения существующей (т. е. ранее заявленных) субъектами. Они не могут быть использованы для введения новая объекты.
и are фактически "повторное открытие" пространства имен для объявления новых сущностей. Если класс
Classпозже определен как член другого пространства имен - это совершенно другой класс, который не имеет ничего общего с тем, кого вы объявили здесь.как только вы доберетесь до точки определение предварительно объявленный класс, вам не нужно снова "открывать" пространство имен. Вы можете определить его в глобальном пространстве имен (или любое пространство имен, содержащее ваш
Namespace) какclass Namespace::Class { /* whatever */ };так как вы ссылаетесь на сущность, которая уже была объявлена в пространстве имен
Namespace, вы можете использовать полное имяNamespace::Class.
вы получаете правильные ответы, позвольте мне просто попробовать заново редакции:
class Namespace::Class;почему я должен это делать?
вы должны сделать это, потому что термин
Namespace::Classговорит компилятор:...Хорошо, компилятор. Найти пространство имен Namespace, а внутри это относится к классу с именем Class.
но компилятор не знает, о чем вы говорите, потому что он ничего не знает пространство имен с именем
Namespace. Даже если бы было пространство имен с именемNamespace, например:namespace Namespace { }; class Namespace::Class;он все равно не будет работать, потому что вы не можете объявить класс в пространстве имен из-за пределов этого пространства имен. Вы должны быть в пространстве имен.
Так, вы можете вперед объявить класс в пространстве имен. Просто сделайте это:
namespace Namespace { class Class; };
Я полагаю, что по той же причине вы не можете объявить вложенные пространства имен за один раз, как это:
namespace Company::Communications::Sockets { }и вы должны сделать это:
namespace Company { namespace Communications { namespace Sockets { } } }
есть много отличных ответов о логическом обосновании, связанном с его запрещением. Я просто хочу предоставить скучную стандартную оговорку, которая специально запрещает это. Это справедливо и для C++17 (n4659).
рассматриваемый абзац [class.name]/2:
декларация, состоящая исключительно из идентификатор ключа класса; либо a повторное объявление имени в текущей области или вперед декларация идентификатор как имя класса. Он вводит класс имя в текущей области.
вышеизложенное определяет, что представляет собой прямое объявление (или 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;из действительного прямого объявления, потому чтоfoo::barне является идентификатором. Это полное имя, что-то другое.
было бы неясно, что на самом деле является типом прямой объявленной переменной. Прямая декларация
class Namespace::Class;может означатьnamespace Namespace { class Class; }или
class Namespace { public: class Class; };
Comments