【问题标题】:Circular Dependecies in C++ / Classes that dpend each otherC++ 中的循环依赖/相互依赖的类
【发布时间】:2013-10-21 00:25:31
【问题描述】:

我有以下问题:

我有一个 Pawn,它站在一块场地上。所以我有 Class Pawn 和 Class Field。我想从 Field 访问站在它上面的 Pawn,我想从 Pawn 访问它所在的 Field。

所以我有课:

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

我做错了什么?

【问题讨论】:

  • 你必须在类定义之外定义有问题的成员函数,在 Filed 的定义可用的地方。

标签: c++ circular-dependency forward-declaration circular-reference


【解决方案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;
    }
};

C++ 文件:

#include <header...>

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

不将多个类放在同一个翻译单元中也是一种普遍接受的做法,但这更像是一种指导,使代码更清晰。

【讨论】:

  • 谢谢,但我遇到了麻烦。我在上面的问题中对其进行了编辑。
  • @Martin 你从不在另一个 cpp 文件中包含一个 cpp 文件。如果您有多个 cpp 文件 - 链接器会将它们链接在一起。
【解决方案2】:

您收到错误的原因是因为您在 Pawn.h 中转发了声明的 Field(这很好!),但您已经实现了一个在头文件中使用 Field 对象的函数。

编译器想知道 intID 是什么,因为您没有指定 Field 的定义。

正如 littleadv 已经很好解释的那样,将它们分开并将标题包含在 .cpp 文件中(或) 删除头文件中的前向声明并包含 Field.h

【讨论】:

    【解决方案3】:

    Pawn类中使用声明而不是定义:

    int getPosition() const;
    

    Field之后,实现它:

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

    (注意我添加了const 作为get 建议此方法不应修改它正在处理的实例)

    您稍后会希望将声明和定义分离到头文件和实现文件中,另一个答案已经包含了一些信息。


    分离标题,创建pawn.hfield.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
    

    【讨论】:

    • 谢谢,但我遇到了麻烦。我在上面的问题中对其进行了编辑。
    • @Martin 编辑了我的答案
    • @Martin 很高兴它有帮助。关心accept the answer
    猜你喜欢
    • 2011-09-18
    • 2013-03-18
    • 1970-01-01
    • 2014-07-27
    • 2018-10-19
    • 1970-01-01
    • 2017-10-12
    • 2011-04-30
    • 1970-01-01
    相关资源
    最近更新 更多