13
votes

My Problem:

Got two classes, class A and B, so i got A.h and A.cpp and B.h and B.cpp. A needs to know B and B needs to know A. I solved it the following way (i don't know why it has to be so...)

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"

I used one forward declaration and it works.

The Problem is, that both classes need to be in the namespace "ui". Or at least I think this is the meaning:

A.h:

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

class A{ ... 

B.h:

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

class B{ ... 

This doesn't work anymore. What do I have to do now to make it work again with namespace and forward declaration?

Both have to be in this namespace. I'm working with Qt and the lines "namespace ui{" etc. are needed. And both classes need to know each other. I already tried just to make this:

namespace ui{
 class A;
 class B;
}

in both headers, but this doesn't work...

Btw: All Header-Files also got the "ifndef"-mechanism.

5
What does "This doesn't work anymore." mean? Please post the exact compiler/linker errors. - fredoverflow

5 Answers

13
votes

If I understand you right, you declare 2 different types with such a construct:

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

class A{ ... }; 

Here you state that there is a class A in the namespace ui, but you define a class A in the global namespace. Therefore ui::A is declared but never defined. Move the definition of A to the ui namespace as well:

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

//somewhere later:
namespace ui
{
  class A{ ... };
}
7
votes
// 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
votes

You're almost there. This should work:

// A.h
namespace ui {

class B;
class A {
  ...
};

} // namespace ui

and

// B.h
namespace ui {

class A;
class B {
  ...
};

} // namespace ui

The only thing you got wrong is that you have to define the classes inside the namespace; it's not enough to forward-declare them inside the namespace.

1
votes

Apart to forward-declare the class from within its namespace (as other answers correctly say), remember to either use (prepend) that namespace when referring to the forward-declared class, or add a using clause:

// B.h
namespace Y { class A; } // full declaration of
// class A elsewhere

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

Ref: Namespaces and Forward Class Declarations

0
votes

This is a very Qt-specific question.

When Qt Designer auto-generates code file for you, the Ui namespace is a separate namespace from your classes. There are actually two different classes being declared here: class A in the global namespace, and class Ui::A in the Ui namespace. The second class holds all of the controls which Qt generates for you (when you use the form designer), and the first class (in the global namespace) has all of your logic.

The version of Qt Creator I'm using (3.1) will also generate a private member for class A (not Ui::A): private: Ui::A* ui;, which is setup with ui->setUp(this). You can then access controls (e.g. ui->lineEdit->toPlainText();.