Circular Dependecies in C++ / Classes that dpend each other

十年热恋 提交于 2019-12-24 16:24:26

问题


i have the following problem:

I have a Pawn, that stands on a Field. So I have the Class Pawn and the Class Field. I want to have access from the Field to the Pawn that stands on it, and I want to have access from the Pawn to the Field it stands on.

So i have classes:

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++ says

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

or

    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«

Is there an other way than declaring things outside the class or do I really have to declare all Methods/Members outside it before I need they?

What can I do? Thank you.

EDIT: Thank you, but i tried now to seperate it into a .h and a .cpp file. Later i will use a .h and a .cpp file for each class, but now i simply have

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

and in main.cpp i include "implementations.cpp"

I get the error

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

What do I do wrong?


回答1:


Separate declarations and implementations. Implement the classes in separate cpp files. Should be like this:

Header file:

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;
    }
};

C++ file:

#include <header...>

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

It is also a generally accepted practice not to put multiple classes in the same translation unit, but that's more of a guidance, makes the code cleaner.




回答2:


The reason you get the error is because you've forward declared Field in Pawn.h (which is good!), but you've implemented a function that uses the Field object within the header file as well.

The compiler is left wondering what intID is, since you've not specified Field's definition.

As littleadv has nicely explained, separate them out and include the header in the .cpp file (or) remove the forward declaration in your header file and include Field.h




回答3:


Use a declaration instead of a definition in the class Pawn:

int getPosition() const;

and after the class Field, implement it:

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

(note I added const as the get suggest that this method should not modify the instance it is working on)

You will later want to separate declarations and definitions into header and implementation files, the other answer already has some information on that.


Separate the headers, create pawn.h and field.h. I think you know how to do that.

Your implementation file pawn.cpp should look something like this:

// 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;
}

You do the same for field.cpp. Then you compile those files separately, also your main.cpp should not include the *.cpp files.

To compile and link everything together, this should get you started:

# 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


来源:https://stackoverflow.com/questions/19343279/circular-dependecies-in-c-classes-that-dpend-each-other

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!