прямое объявление с вектором типа класса - указатель на неполный тип класса недопустим - PullRequest
9 голосов
/ 10 октября 2011

У меня есть два класса, foo и bar.

foo.h #include s bar.h и содержит std::vector указателей на bar объектов. В какой-то момент во время выполнения bar должен получить доступ к этому вектору указателей на другие bar объекты. Следовательно, foo содержит метод с именем getBarObjects(), который возвращает массив указателей.

Поэтому я пересылаю объявление foo в bar.h. Я, очевидно, также должен заранее объявить метод, который я использую - foo::getBarObjects(). Когда это возвращает массив указателей на bar, я попадаю в порочный круг.

Я не могу переслать объявление Bar, а затем просто переслать объявление getBarObjects(), поскольку это приводит к тому, что «неполное имя типа не разрешено».

foo.h:

#include "bar.h"
#include <vector>

class foo {
    public:
         foo();
         ~foo();
         std::vector<bar*> getBarObjects();
    private:
         std::vector<bar*> barObjects;
}

bar.h:

class foo;
std::vector<bar*> foo::getBarObjects();        // error, doesn't know bar at this point

class bar {
    public:
        bar(foo *currentFoo);
        ~bar();
        bool dosth();
    private:
        foo *thisFoo;
}

bar.cpp:

#include "bar.h"

bool bar(foo *currentFoo) {
    thisFoo = currentFoo;
}

bool bar::dosth() {
    thisFoo->getBarObjects();        // error, pointer to inomplete class type is not allowed
}

Если я просто включу наоборот, у меня точно такая же проблема будет в foo позже. Есть предложения?

Ответы [ 3 ]

19 голосов
/ 10 октября 2011

Вы не можете переслать объявление участников.

Вместо этого bar.cpp должен #include и foo.h, и bar.h. Проблема решена.

В общем случае, если вы используете последовательность:

  • Вперед, объявить все типы классов
  • Определить все типы классов
  • Органы учащихся

все будет хорошо.

6 голосов
/ 10 октября 2011

Вам не нужно включать foo.h или bar.h друг от друга, если только вы не обращаетесь к внутренним элементам одного класса из другого заголовочного файла. Объявите классы по необходимости в заголовочных файлах, затем включите оба заголовочных файла из исходного файла.

foo.h

#include <vector>
class bar;
class foo {
    public:
         foo();
         ~foo();
         std::vector<bar*> getBarObjects();
    private:
         std::vector<bar*> barObjects;
};

bar.h

class foo;
class bar {
    public:
        bar(foo *currentFoo);
        ~bar();
        bool dosth();
    private:
        foo *thisFoo;
}

bar.cpp

#include "foo.h"
#include "bar.h"

bool bar(foo *currentFoo) {
    thisFoo = currentFoo;
}

bool bar::dosth() {
    thisFoo->getBarObjects();
}
1 голос
/ 10 октября 2011

Вы забыли переслать объявление вектора в foo.h.Вы также возвращаете vector побочное значение из getBarObjects, что, возможно, не то, что вам нужно, и предварительное объявление функции-члена бесполезно.

Также: используйте защиту заголовков.Предпочитайте соответствующий интеллектуальный указатель для вашей ситуации (std::shared_ptr, unique_ptr) над необработанными указателями.Остерегайтесь const Несс.

...