прямое объявление и пространства имен (c ++) - PullRequest
13 голосов
/ 22 июня 2011

Моя проблема:

У меня два класса, класс A и B, поэтому я получил Ah и A.cpp и Bh и B.cpp.A должен знать B, а B должен знать A. Я решил это следующим образом (я не знаю, почему это так ...)

Ах:

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

A.cpp:

#include "A.h"

Bh:

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

B.cpp:

#include "B.h"

Я использовал одно предварительное объявление, и оно работает.

Проблема в том, что оба класса должны находиться в пространстве имен "ui".Или, по крайней мере, я думаю, что это значение:

Ах:

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

class A{ ... 

Bh:

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

class B{ ... 

Это больше не работает.Что мне теперь нужно сделать, чтобы он снова работал с пространством имен и предварительным объявлением?

Оба должны быть в этом пространстве имен.Я работаю с Qt, и нужны строки "namespace ui {" и т. Д.И оба класса должны знать друг друга.Я уже пытался просто сделать это:

namespace ui{
 class A;
 class B;
}

в обоих заголовках, но это не работает ...

Кстати: все файлы заголовков также получили механизм "ifndef".

Ответы [ 5 ]

13 голосов
/ 22 июня 2011

Если я вас правильно понимаю, вы объявляете 2 различных типа с такой конструкцией:

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

class A{ ... }; 

Здесь вы утверждаете, что в пространстве имен ui есть *1005*, но вы определяете class A в глобальном пространстве имен.Следовательно, ui::A объявлено, но никогда не определено .Переместите определение A также в пространство имен ui:

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

//somewhere later:
namespace ui
{
  class A{ ... };
}
7 голосов
/ 22 июня 2011
// 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 голосов
/ 22 июня 2011

Ты почти у цели. Это должно работать:

// A.h
namespace ui {

class B;
class A {
  ...
};

} // namespace ui

и

// B.h
namespace ui {

class A;
class B {
  ...
};

} // namespace ui

Единственное, что вы ошиблись, это то, что вы должны определить классы внутри пространства имен; недостаточно просто объявить их в пространстве имен.

1 голос
/ 31 октября 2018

Помимо прямого объявления класса из его пространства имен (как правильно говорят другие ответы), не забудьте либо использовать (предварять) это пространство имен при обращении к классу, объявленному вперед, либо добавить using пункт:

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

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

Ссылка: Пространства имен и объявления класса Forward

0 голосов
/ 05 января 2015

Это очень специфичный для Qt вопрос.

Когда Qt Designer автоматически генерирует файл кода для вас, пространство имен Ui является отдельным пространством имен от ваших классов. На самом деле здесь объявлено два разных класса: class A в глобальном пространстве имен и class Ui::A в Ui пространстве имен. Второй класс содержит все элементы управления, которые Qt генерирует для вас (когда вы используете конструктор форм), а первый класс (в глобальном пространстве имен) содержит всю вашу логику.

Версия Qt Creator, которую я использую (3.1), также сгенерирует приватный член для class A (не Ui::A): private: Ui::A* ui;, который настроен на ui->setUp(this). Затем вы можете получить доступ к элементам управления (например, ui->lineEdit->toPlainText();.

...