Круговые зависимости в C ++ / Классы, которые дополняют друг друга

у меня следующая проблема:

У меня есть пешка, которая стоит на поле. Итак, у меня есть Пешка класса и Поле класса. Я хочу иметь доступ с Поля к Пешке, которая стоит на ней, и я хочу иметь доступ от Пешки к Полю, на котором она стоит.

Итак, у меня есть классы:

class Pawn;
class Player;
class Field;
class PlayerList;

class Pawn
{
public:
int intID;
Player* plrPlayer;
Field* fldField;

...

int getPosition()
{
//gets the ID of the Field it stands on
return fldField->intID; //Here i get the error
}
}

class Field
{
public:
Pawn* pwnPawn;
int intID;
Field()
{
intID = -1;
}
Field(int intIDParam)
{
intID = intIDParam;
}
};

G ++ говорит

Error: invalid use of incomplete type "class Field"Error: Forward declaration of class Field

или же

    main.cpp: In Elementfunktion »int Pawn::getPosition()«:
main.cpp:42:24: Fehler: falsche Benutzung des unvollständigen Typs »class Field«
main.cpp:10:7: Fehler: Vorwärtsdeklaration von »class Field«

Есть ли другой способ, кроме объявления вещей вне класса, или мне действительно нужно объявить все методы / члены за его пределами, прежде чем они мне понадобятся?

Что я могу сделать? Спасибо.

РЕДАКТИРОВАТЬ:
Спасибо, но я попытался разделить его на файлы .h и .cpp. Позже я буду использовать файлы .h и .cpp для каждого класса, но теперь у меня просто есть

header.h

#ifndef _HEADERS_
#define _HEADERS_
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <vector>
using namespace std;

class Pawn;
class Player;
class Field;
class PlayerList;

class Pawn
{
public:
int intID;
Player* plrPlayer;
Field* fldField;

//Constructors....

int getPosition();
...
};
#endif

implementations.cpp

#ifndef _IMPLEMENTATIONS_
#define _IMPLEMENTATIONS_
#include "headers.h"//Pawn.cpp
int Pawn::getPosition()
{
return fldField->intID;
}

...

#endif

и в main.cpp я включаю «Implementations.cpp»

Я получаю ошибку

In function Pawn::getPosition
multiple definition of Pawn::getPosition

Что я делаю не так?

1

Решение

Отдельные объявления и реализации. Реализуйте классы в отдельных файлах cpp. Должно быть так:

class Player;
class Field;
class PlayerList;

class Pawn
{
public:
int intID;
Player* plrPlayer;
Field* fldField;

...

int getPosition();

}

class Field
{
public:
Pawn* pwnPawn;
int intID;
Field()
{
intID = -1;
}
Field(int intIDParam)
{
intID = intIDParam;
}
};
#include <header...>

int Pawn::getPosition()
{
//gets the ID of the Field it stands on
return fldField->intID; //Here i get the error
}

Это также общепринятая практика — не помещать несколько классов в одну единицу перевода, но это скорее руководство, которое делает код чище.

0

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

Причина, по которой вы получаете ошибку, заключается в том, что вы перенаправили объявленное поле в Pawn.h (что хорошо!), Но вы реализовали функцию, которая также использует объект Field в заголовочном файле.

Компилятору остается задаться вопросом, что такое intID, поскольку вы не указали определение Field.

Как мило объяснил littleadv, выделите их и включите заголовок в файл .cpp (или)
удалите предварительную декларацию в вашем заголовочном файле и включите Field.h

0

Используйте объявление вместо определения в классе Pawn:

int getPosition() const;

а также после класс Field, внедри это:

int Pawn::getPosition() const
{
//gets the ID of the Field it stands on
return fldField->intID;
}

(примечание я добавил const как get предположить, что этот метод не должен изменять экземпляр, на котором он работает)

Позже вы захотите разделить объявления и определения в файлах заголовка и реализации, другой ответ уже содержит некоторую информацию об этом.


Разделите заголовки, создайте pawn.h а также field.h, Я думаю, вы знаете, как это сделать.

Ваш файл реализации pawn.cpp должен выглядеть примерно так:

// note: no include guards for the
#include "pawn.h" // you need the header for pawn
#include "field.h" // and the header for field since here you are using it

int Pawn::getPosition()
{
return fldField->intID;
}

Вы делаете то же самое для field.cpp, Затем вы компилируете эти файлы отдельно, а также ваши main.cpp не должен включать *.cpp файлы.

Чтобы скомпилировать и связать все вместе, вы должны начать:

# compile each source file into an object file
g++ -Wall -c field.cpp -o field.o
g++ -Wall -c pawn.cpp -o pawn.o
g++ -Wall -c main.cpp -o main.o
# link them together into an executable
g++ field.o pawn.o main.o -o main
# run the executable
./main
0