前置声明和命名空间(C++)

13
我的问题:
有两个类,A类和B类,因此我有A.h和A.cpp以及B.h和B.cpp。 A需要知道B,而B需要知道A。我通过以下方式解决了这个问题(我不知道为什么必须这样做…)。

A.h:

#include "B.h"
class A{ ... 

A.cpp:

#include "A.h"

B.h:

#include "A.h"
class A; // forward declaration
class B { ... 

B.cpp:

#include "B.h"

我使用了一个前向声明,它起作用了。
问题是,这两个类都需要在命名空间“ui”中。或者至少我认为这是意思:

A.h:

#include "B.h"
namespace ui{
  class A;
}

class A{ ... 

B.h:

#include "A.h"
namespace ui{
  class B;
}

class B{ ... 

这个不再起作用了。现在我该怎么做才能使它再次与命名空间和前向声明一起工作?
两者都必须在同一个命名空间中。我正在使用Qt,需要使用"namespace ui{"等语句。并且两个类需要相互知道。 我已经尝试过只是这样做:
namespace ui{
 class A;
 class B;
}

在两个头文件中都有,但是这并不起作用...
顺便说一下:所有的头文件也都有“ifndef”机制。

3
“ This doesn't work anymore.” 意思是“这不再起作用了”。请发布确切的编译器/链接器错误信息。 - fredoverflow
5个回答

13

如果我理解正确,您使用这样的结构声明了2种不同的类型:

#include "B.h"
namespace ui{
  class A;
}

class A{ ... }; 

你在这里声明命名空间 ui 中有一个 class A,但是你在全局命名空间中定义了一个 class A。因此,ui::A 被声明但是从未被定义。将 A 的定义也移动到 ui 命名空间中:

#include "B.h"
namespace ui{
  class A;
}

//somewhere later:
namespace ui
{
  class A{ ... };
}

7
// A.h
namespace ui {
   class A; // forward
   class B {
   };
}



// B.h
namespace ui {
   class B; // forward
   class A {
   };
}



// A.cpp
#include "A.h"
#include "B.h"



// B.cpp
#include "A.h"
#include "B.h"

3
你已经快成功了。这应该可以运行:

// A.h
namespace ui {

class B;
class A {
  ...
};

} // namespace ui

并且

// B.h
namespace ui {

class A;
class B {
  ...
};

} // namespace ui

您唯一做错的事情就是必须在命名空间内定义类;仅在命名空间中进行前向声明是不够的。


我做不到这个。这是QT-Designer自动生成的文本。它只是这样做。我不知道为什么。顺便说一下,在我第一个例子中,我还需要两个前向声明。 - Obs
你可能已经注意到,你得到了三个几乎完全相同的答案?这是使其工作的唯一方法。如果QT-Designer不能被说服将其类定义放在“namespace ui { ... }”块内,那么你就只能让这些类位于全局命名空间中。 - zwol

1
除了在其命名空间内前向声明类(正如其他答案所说),请记得在引用前向声明的类时要使用(前置)该命名空间,或者添加一个using子句:
// B.h
namespace Y { class A; } // full declaration of
// class A elsewhere

namespace X {
    using Y::A;   // <------------- [!]
    class B {
        A* a; // Y::A
    };
}

参考: 命名空间和前置类声明


0

这是一个非常Qt特定的问题。

当Qt Designer为您自动生成代码文件时,Ui命名空间是与您的类分开的。实际上,在此处声明了两个不同的类:全局命名空间中的A类Ui命名空间中的A类。第二个类包含Qt为您生成的所有控件(当您使用表单设计器时),而第一个类(在全局命名空间中)具有您的所有逻辑。

我正在使用的Qt Creator版本(3.1)还将为class A(而不是Ui::A)生成一个私有成员:private: Ui::A* ui;,它设置为ui->setUp(this)。然后,您可以访问控件(例如ui->lineEdit->toPlainText();)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接