[英]Why can't I forward-declare a class in a namespace using double colons?
class Namespace::Class;
我為什么要這樣做?:
namespace Namespace {
class Class;
}
使用VC ++ 8.0,編譯器會發出:
錯誤C2653:'Namespace':不是類或命名空間名稱
我假設這里的問題是編譯器無法判斷Namespace
是類還是命名空間? 但是,為什么這只是一個前瞻宣言呢?
是否有另一種方法來轉發聲明在某個命名空間中定義的類? 上面的語法感覺就像我“重新打開”命名空間並擴展其定義。 如果Class
實際上沒有在Namespace
定義怎么辦? 這會在某個時候導致錯誤嗎?
你得到了正確答案,讓我試着重新措辭:
class Namespace::Class;
為什么我要這樣做?
你必須這樣做,因為術語Namespace::Class
告訴編譯器:
......好的,編譯器。 找到名為Namespace的命名空間,並在其中引用名為Class的類。
但編譯器不知道你在說什么,因為它不知道任何名為Namespace
命名Namespace
。 即使有名為Namespace
命名Namespace
,如下所示:
namespace Namespace
{
};
class Namespace::Class;
它仍然無法工作,因為您無法在該命名空間外部聲明一個類。 您必須在命名空間中。
因此,您實際上可以在命名空間中轉發聲明一個類。 這樣做:
namespace Namespace
{
class Class;
};
因為你做不到。 在C ++語言中,完全限定名稱僅用於引用現有 (即先前聲明的)實體。 它們不能用於引入新實體。
事實上,您正在 “重新打開”命名空間以聲明新實體。 如果類Class
稍后被定義為不同命名空間的成員 - 它是一個完全不同的類,與您在此處聲明的類無關。
一旦達到定義預先聲明的類的程度,就不需要再次“重新打開”命名空間。 您可以在全局命名空間(或包含Namespace
任何命名Namespace
)中將其定義為
class Namespace::Class {
/* whatever */
};
由於您指的是已在命名空間Namespace
聲明的實體,因此可以使用限定名稱Namespace::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 :
僅由類密鑰標識符組成的聲明; 是對當前作用域中名稱的重新聲明,或者是作為類名稱的標識符的前向聲明。 它將類名引入當前范圍。
以上定義了什么構成了前瞻性聲明(或類的重新聲明)。 從本質上講,它必須是class identifier;
, struct identifier;
或union identifier;
其中, identifer是[lex.name]中常見的詞法定義:
identifier: identifier-nondigit identifier identifier-nondigit identifier digit identifier-nondigit: nondigit universal-character-name nondigit: one of abcdefghijklm nopqrstuvwxyz ABCDEFGHIJKLM NOPQRSTUVWXYZ _ 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
不是標識符。 這是一個完全合格的名稱,不同的東西。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.