Ошибки C ++: & quot; ‘class’ не называет тип & quot; и & quot; неверное использование неполного типа ‘struct … ‘& quot;

Это очень повторяющаяся проблема, также здесь, в StackOverflow, но мне не удается решить мою проблему, даже пытаясь найти разные ответы. Итак, у меня есть несколько классов:

main.cpp:

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

foo.h:

#include "bar.h"class foo {
foo();
bar& bind(bar &b);
gru& bind(gru &g);
};

bar.h:

#include "foo.h"class bar {
bar();
foo& bind(foo &f);
gru& bind(gru &g);
};

Ясно, что у меня есть циклическая зависимость. Так я получаю позорную ошибку 'bar' does not name a type, В этом случае я добавляю class bar; в foo декларацию и удалить #include, Когда я это делаю, я получаю: invalid use of incomplete type ‘struct bar',

Я пытался разными способами, также добавляя class foo; в бар, но у меня всегда есть какая-то ошибка. В этом последнем случае я получаю:

bar.cpp:48:11: error: prototype for ‘foo& bar::bind(bar::foo&)’ does not match any in class ‘bar’
bar.h:55:12: error: candidates are: gru& bar::bind(gru&)
bar.h:54:13: error:                 bar::foo& bar::bind(bar::foo&)

Кроме того, я никогда не получаю жалоб gru, Который, как дополнительная информация, уже был в этой программе, прекрасно работает вместе с bar а также mainпрежде чем я добавил foo,

Есть полезные идеи? Большое спасибо 🙂

0

Решение

в foo.h

  #pragma once //(or use a guard symbol)
class bar;
class foo
{
bar & bind(bar & b);
};

в бар.ч

  #pragma once //(or use a guard symbol)
class foo;
class bar
{
foo & bind(foo & f);
};

в foo.cpp

#include <foo.h>
#include <bar.h>

bar foo:bind(bar & b)
{
// here you can use bar methods
}

в bar.cpp

#include <bar.h>
#include <foo.h>

foo bar:bind(foo & f)
{
// here you can use foo methods
}
1

Другие решения

Для меня это будет хорошо скомпилировано (ПРИМЕЧАНИЕ: это без создания экземпляра класса foo или bar):

ФАЙЛ bar.h СОДЕРЖИТ:

#ifndef BAR_H
#define BAR_H

#include "foo.h"
class foo;
class gru;

class bar {

bar();
foo& bind(foo &f);
gru& bind(gru &g);
};

#endif

ФАЙЛ foo.h СОДЕРЖИТ:

#ifndef FOO_H
#define FOO_H
#include "bar.h"class bar;
class gru;
class foo {
foo();
bar& bind(bar &b);
gru& bind(gru &g);
};

#endif

ГЛАВНЫЙ .cpp ФАЙЛ СОДЕРЖИТ:

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

Большое спасибо, ребята, за ответы. Во многом они были полезны.

В конце концов я понял, что мне нужно изменить порядок всех #includeЭто в моем коде, потому что, как вы, возможно, поняли, кодирования было намного больше, и я поместил здесь более простую версию (извините за это).

Итак, мое окончательное решение было включить class bar; в foo.h а также class foo; в bar.h, Затем измените порядок включения в main.cpp и Makefile.

Еще раз спасибо 😉

0

C ++ Компилятор очень старый, и, кроме того, часть, которая обрабатывает этот пример в вашем коде, является не самим компилятором, а частью цепочки компиляторов, известной как препроцессор. Если мы можем договориться о C ++ Компилятор не очень умен, препроцессор — скучный, но дружелюбный помощник.

Файл * .cpp компилируется, а затем связывается с другими файлами * .cpp в вашей программе. Файлы .h на самом деле сами по себе не имеют никакого значения: это разделение предположительно является преимуществом для программистов. Ключевым моментом здесь является то, что, независимо от того, сколько * .h файлов вы включили в ваш * .cpp файл, в конечном итоге будет просто огромный сгенерированный файл cpp, содержащий весь код, присутствующий в ваших * .h файлах, а также исходный код присутствует в самом файле * .cpp.

Циклическая зависимость может быть решена многими способами, но, как вы можете себе представить, компилятор даже не имеет возможности обработать что-либо до того, как возникнет проблема. Циклические зависимости не поддерживаются в C или C ++.

Более современные компиляторы, такие как Джава или же C #, могут извлечь открытый интерфейс классов и использовать эту информацию, когда A класс нужен для B класс и наоборот. Опять же, это невозможно в C ++.

Единственным решением было бы переписать ваш код. Целью является устранение циклического #include директивы. На самом деле, если ваш код так же прост, как вы показываете здесь, вы можете легко решить его, используя предварительное объявление:

// foo.h
class bar;

class foo {
foo();
bar& bind(bar &b);
gru& bind(gru &g);
};

// bar.h
class foo;

class bar {
bar();
foo& bind(foo &f);
gru& bind(gru &g);
};

// main.cpp
#include "foo.h"#include "bar.h"
// ...
int main()
{
// ...
}

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

Здесь работают другие концепции, такие как, например, защита компилятора.

Надеюсь это поможет.

0