C ++名称空间 - 嵌套名称空间的前向声明和可见性

时间:2016-11-02 09:32:24

标签: c++ namespaces

这是一个非常基本的问题,但实际上我从未定义过命名空间。我正在尝试将基于Qt的库中的类分组到各种名称空间中(并且还允许更容易的扩展而不会出现名称冲突)。例如,主类(也代表库)属于顶级命名空间lib

namespace lib {
    class LibClass;
}

这个LibClass使用了一堆其他名称空间和类,这些名称空间和类在LibClass标题中包含的其他标题文件中定义:

#include <QObject>
#include "libclass_global.h"
#include "Manager.h"
#include "Configurator.h"

namespace lib {
    class LibClass;
}

class LIBCLASSSHARED_EXPORT LibClass : public QObject {
    public:
        LibClass();
        ...
    signals:
        ...
    private slots:
        ...
    public slots:
        ...
    private:
        lib::core::communication::Manager manager;             // PROBLEM HERE
        lib::core::communication::Configurator configurator;   // PROBLEM HERE
}

Manager.h 包含

namespace lib {
    namespace core {
        namespace communication {
            class Manager;
        }
    }
}

class Manager {
    public:
        Manager();
        ...
    private:
        ...
}

Configurator.h 包含

namespace lib {
    namespace core {
        namespace communication {
            class Configurator;
        }
    }
}

class Configurator {
    public:
        Configurator();
        ...
    private:
        ...
}

这里的课程内容并不重要。

编译后,我得到名称空间core中的q3dtp没有命名类型。所以基本上从我的理解,我需要在我的LibClass的标题中使用前向声明,因为名称空间似乎实际上不包括插入包含那些的头文件(由于某种原因):

namespace lib {
    class LibClass;

    namespace core {
        namespace communication {
            class Manager;
            class Configurator;
        }
    }
}

问题在于,现在我只限于指针,因为我正在向前声明ManagerConfigurator。我想尽可能避免动态分配东西(而不是需要)。

所以这里的问题是如何解决这个问题?我显然可以将所有类声明移动到相同的标头及其定义到同一源文件。然而,这将使得将来很难维护。仅声明子命名空间似乎也没有解决问题 - 我得到两个类都没有命名类型,并且LibClass没有成员名<name_of_class_from_nested_namespace>

2 个答案:

答案 0 :(得分:5)

您对LibClass的声明是错误的。它应该是:

namespace lib {
    class LibClass;
}

class lib::LibClass {
    ...
};

namespace lib {
    class LibClass {
        ....
    };
}

目前的情况是,您宣布lib::LibClass并定义::LibClass(两个完全不同的类)。

这也适用于所有其他课程。

答案 1 :(得分:2)

当你这样做时

namespace ns {
  class cls;
};

class cls {
};

您转发声明一种类型,然后定义另一种。您需要限定班级名称:

namespace ns {
  class cls;
};

class ns::cls {
};

随着c ++ 17的出现,如果嵌套命名空间变得过于繁琐,您可以执行以下操作:

namespace ns1::ns2::ns3 {

  class cls {
  };

}