CIrcular Inclusion

时间:2016-03-19 14:52:49

标签: c++ class include

我正在构建一个俄罗斯方块,并试图避免指针。在下面的代码中,我尝试在另一个类" TetrisWindow" 中定义类" ButtonQuit" 的实例,这两个类都是互相使用'方法。我一直收到错误:

‘ButtonQuit’ does not name a type: ButtonQuit btnQuit;

或:

field ‘btnQuit’ has incomplete type: ButtonQuit btnQuit;

我知道有一个循环包含,但我无法弄清楚如何解决这个问题。我已经尝试过宣布 ButtonQuit ,但它无法正常工作。

WindowSDL 只是一个包含所有图形功能的类,除了SDL之外,它没有包含它。)

这是我的代码(当我编译这个时,我得到"没有命名类型"错误):

BUTTONQUIT.HPP:

#ifndef __BUTTONQUIT__
#define __BUTTONQUIT__

#include <TetrisWindow.hpp>

class ButtonQuit{

private:

int x,y;
TetrisWindow win;

public:

ButtonQuit (TetrisWindow, int, int);
~ButtonQuit();
void print(void);
void action(void);
bool clicked(int, int);


};

#endif

TETRISWINDOW.HPP:

#ifndef __TETRISWINDOW__
#define __TETRISWINDOW__

#include <cstdint>
#include <string>
#include <vector>

#include <WindowSDL.hpp>
#include <ButtonQuit.hpp>

class TetrisWindow: public WindowSDL{

protected:

ButtonQuit btnQuit;
void handleEvent(SDL_Event&);
void work(void);

public:

TetrisWindow();
TetrisWindow(uint16_t, uint16_t);
TetrisWindow(const TetrisWindow& w);
~TetrisWindow();

void drawWindow(void);

};

#endif

2 个答案:

答案 0 :(得分:2)

问题不在于您的情况下的循环包含,这是次要问题。

您应该考虑的第一个问题是TetrisWindowButtonQuit成员,而ButtonQuitTetrisWindow成员。

这两个成员不是指针也不是引用,这意味着它们将以包含类的整个大小存储。这导致了一个不会结束的递归结构。

TetrisWindow必须包含ButtonQuit,其中必须包含TetrisWindow,其中必须包含ButtonQuit ...

这里的解决方案是在相应的其他标头中转发声明这两个类,并使用指针/引用,例如:

// TetrisWindow.h
class ButtonQuit;

class TetrisWindow {
  private:
    ButtonQuit* button;
  ...
}

// ButtonQuit.h
class TetrisWindow;

class ButtonQuit {
  private:
    TetrisWindow* window;
  ...
}

现在您使用指针作为成员,因此编译器不必知道sizeof(ButtonQuit)sizeof(TetrisWindow)的定义,因为指针始终是指针。这样您就可以根本不包含其他类的标题,只要您没有尝试访问不完整类型的内联函数。

答案 1 :(得分:1)

您的班级TetrisWindowButtonQuit(以及一些会员功能)组成。此ButtonQuit还有一个TetrisWindow类型的成员(其成员类型为ButtonQuit,其成员类型为TetrisWindow ....)。

有了这个看法,你就无法解决问题,两个人都是不可能的。

你需要的是某种“知道”而不是“由......组成”的关系。

通常这是通过指针完成的,因此让ButtonQuit成员TetrisWindow* parent可能是有意义的 - 这是一个非拥有指针,你可以声明你的TetrisWindow例如作为具有自动存储持续时间的全局变量(这意味着不需要delete)。

“知道”关系的另一个选择是引用,但需要在构造函数中设置引用 - 这意味着您需要在TetrisWindow和{{1}之前构造ButtonQuitButtonQuit之前。