如果我这样做,我的前瞻声明就不起作用了:
class Manager::TagManager;
namespace UI
{
class Example
{
public:
...
Manager::TagManager* tagManager_;
};
}
它表示使用未定义的类型。但它的工作原理如下:
namespace Manager
{
class TagManager;
}
//same stuff follows
那么差异是什么? 是“类管理器:: TagManager;”不是命名空间管理器中的TagManager声明吗?
答案 0 :(得分:2)
一个修辞问题:您希望编译器如何知道class Manager::TagManager
是名称空间TagManager
中的类Manager
的声明还是嵌套类TagManager
的声明上课Manager
?编译器之前从未听说过Manager
。它不知道它是类还是命名空间。这是编译器试图通过该错误消息告诉您的内容。它实际上假设Manager
是一个类类型(不是命名空间),尚未定义。
但是,即使它知道Manager
是什么,它仍然无效。在C ++中,像Name1::Name2
这样的限定名称只能用于引用现有的(即已经声明的)实体。您不能使用限定名称来声明 new 实体。
这意味着属于命名空间的实体的前向声明只能通过重新打开该命名空间来完成。嵌套在类中的实体的前向声明只能在封闭类的定义内完成。
对于名称空间中的实体,它相对容易,因为您可以根据需要重新打开名称空间。对于类中的嵌套实体,您只有一次机会。
答案 1 :(得分:0)
不幸的是,在我看来,这是一种语言的设计缺陷。它应该以相同的方式工作,除非它没有。
答案 2 :(得分:0)
不,你从未告诉编译器Manager
是名称空间。它可能是class Manager
。 (这可能就是为什么它说“未定义类型”,错误消息不考虑它是命名空间的可能性。)
您无法将成员添加到其自定义范围之外的任何内容。如果您可以在没有名称空间声明的情况下在名称空间中声明某些东西,那么它会破坏关注点的分离。
如果您必须在Manager::TagManager
中没有声明该特定类的情况下使用名称Manager
,则可以在using namespace
中使用Manager
声明并声明该类另一名称空间在规则中偶尔会有其他方法必须在封闭实体中声明事物,但它们只是名称查找黑客,并且不会改变拥有或包含内容的内容。