2

如果我这样做,我的前向声明不起作用:

class Manager::TagManager;

namespace UI
{

    class Example
    {
    public:
    ...

    Manager::TagManager* tagManager_;


    };
}

它说使用未定义的类型。但是它像这样工作正常:

namespace Manager
{
     class TagManager;
}

//same stuff follows

那么有什么区别呢?是“类管理器::TagManager;” 不是命名空间管理器中的 TagManager 声明?

4

3 回答 3

2

一个反问:您希望编译器如何知道class Manager::TagManagerTagManager命名空间中的类声明还是封闭类Manager中的嵌套类声明?编译器以前从未听说过。它不知道它是一个类还是一个命名空间。这就是编译器试图通过该错误消息告诉您的内容。它实际上假定这是一个尚未定义的类类型(不是命名空间)。TagManagerManagerManagerManager

但是,即使它知道是什么Manager,它仍然无法工作。在 C++ 中,限定名称 likeName1::Name2只能用于引用现有(即已声明的)实体。您不能使用限定名称来声明实体。

这意味着一个属于命名空间的实体的前向声明只能通过重新打开该命名空间来完成。嵌套到类中的实体的前向声明只能在封闭类的定义内完成。

使用命名空间中的实体相对容易,因为您可以根据需要多次重新打开命名空间。使用类中的嵌套实体,您只有一次机会。

于 2013-07-04T00:22:42.003 回答
0

不幸的是,在我看来,这是该语言的设计缺陷。无论哪种方式,它都应该以相同的方式工作,但事实并非如此。

于 2013-07-03T23:17:08.113 回答
0

不,您从未告诉编译器这Manager是一个命名空间。可能是class Manager。(这可能就是为什么它说“未定义类型”,错误消息没有考虑它是命名空间的可能性。)

您不能将成员添加到其自身定义范围之外的任何内容。如果您可以在没有命名空间声明的情况下在命名空间中声明某些内容,则会破坏关注点分离。

如果您必须在Manager::TagManager没有在 中声明该特定类的情况下使用名称Manager,则可以在内部使用using namespace声明Manager并在另一个命名空间中声明该类。有时还有其他方法可以绕过必须在其封闭实体中声明事物的规则,但它们只是名称查找黑客,不会改变拥有或包含什么。

于 2013-07-04T00:04:40.017 回答