У меня есть 3 класса:

Class.h

ClassA
{
    public:
        ClassA();
};

ClassB.h

#include "ClassA.h"

classB
{
    public:
        ClassB();

    private:
        ClassA m_classA;
};

ClassC.h

#include "ClassB.h"

ClassC
{
    public:
        ClassC();

    private:
        ClassB m_classB;
};

ClassC нужен ClassB, а ClassB нужен ClassA. ClassC не нуждается в ClassA, поэтому я должен поместить #include "ClassA.h" внутри заголовка ClassB внутри исходного файла и сделать глобальный объект или есть лучший способ?

ClassB.cpp

#include "ClassB.h"
#include "ClassA.h"

ClassA g_classA;
c++
0
James Moore 18 Янв 2013 в 01:15
4
Форвардные объявления не объявляют полные типы, он не использует указатели.
 – 
imreal
18 Янв 2013 в 01:16
Похоже, я неправильно понял вопрос.
 – 
Rapptz
18 Янв 2013 в 01:20

1 ответ

Лучший ответ

ClassB имеет объект ClassA, поэтому для его объявления класса требуется полное объявление ClassA. Поэтому вам необходимо включить заголовок ClassA.h в ClassB.h * , независимо от того, что происходит с ClassC.

Если вы не хотите включать заголовки, вы можете сохранить (умный) указатель на classA и объявить его вперед. Тогда вам нужно только включить classA.h в classB.cpp. Вот простой пример:

Через A.h

class A {};

Через B.h

#include <unique_ptr>

class A; // forward declaration of A

class B {
 public:
  B();
 private:
  std::unique_ptr<A> a_; // C++11 smart pointer expressing unique ownership
};

Через B.cpp

#include "B.h"
#include "A.h" // we need the full declaration here.

B::B() : a_(new A()) {}

* Строго говоря, ClassA.h может быть включен в другие файлы, если он косвенно включен в ClassB.h. Но лучше включать то, что вам нужно, там, где вам это нужно, и не зависеть от косвенных включений.

3
juanchopanza 18 Янв 2013 в 02:19
Абсолютно верно для написанного кода, но ... вы можете использовать pimpl, чтобы разорвать зависимость.
 – 
Ben Voigt
18 Янв 2013 в 01:19
Включение ClassA.h до ClassB.h работает так же хорошо, как включение его внутрь ClassB.h. Это может быть хороший совет, но это не единственный способ.
 – 
Mark Ransom
18 Янв 2013 в 01:21
Правда, я добавил на это сноску.
 – 
juanchopanza
18 Янв 2013 в 01:25
Если бы вы работали над большим проектом, и ClassB начал расти с включением нескольких классов, вы бы все равно включали все эти заголовки в заголовок ClassB и создавали бы там объекты. Или включить заголовки в исходный файл ClassB и создать объекты глобального класса и пропустить объявления заголовков?
 – 
James Moore
18 Янв 2013 в 01:45
«объекты глобального класса» - это ортогональное понятие. С членом данных определенного типа, как и у вас, каждый экземпляр содержащего класса имеет свой собственный экземпляр содержащегося типа. Если вы хотите минимизировать зависимости во время компиляции, вы можете сделать так, чтобы ваши классы содержали (умные) указатели на другие типы и пересылали объявление этих типов в заголовок вместо включения их заголовка. Затем включите заголовок в исходный файл. Добавлю небольшой пример.
 – 
juanchopanza
18 Янв 2013 в 01:51