代码之家  ›  专栏  ›  技术社区  ›  Pingus

我在一个类中封装了功能,但现在该类不能使用我从使用它的类中需要的功能

  •  0
  • Pingus  · 技术社区  · 3 年前

    我正在制作一个Qt应用程序,它是TicTacToe的变体,可以创建多个板。在游戏板所在的窗口类(PlayGameWindow)中,我有很多处理板的函数,并在它们之间传递相同的3+变量。将他们全部转移到董事会班级是有意义的。Board类有一个QGridLayout作为板和符号空间的标签(例如3x3标签)。

    我有一个(修改的)QLabels的点击监听器,所以当用户按下空格时,它会对板进行一些操作。在比赛期间,我还需要与球员们一起工作。(监听器使用的函数是Board类中唯一需要调用PlayGameWindow函数的地方。)例如,我需要迭代到下一个玩家,或者获取当前玩家符号以放入空间。

    我不确定该分享哪些代码来帮助这篇文章。以下是与板空间点击监听器相关的两个功能。在这个版本中,spaceClicked是一个朋友函数,addClickedSpace使用的是由PlayGameWindow设置的类变量gameW。

    void Board::addClickedSpace(BoardSpaceLabel* space)
    {
        QObject::connect(space, &BoardSpaceLabel::clicked, this,
            [this, space]() { spaceClicked(space, this, gameW); }
        );
    }
    
    void spaceClicked(BoardSpaceLabel* space, Board* b, PlayGameWindow* w)
    {
        // if space has text or image
        if (space->getSymbol() != "")  return;
    
        space->setSymbol(w->getCurrPlayerSymbol());
    
        QVector<QVector<BoardSpaceLabel*>> wins = b->getWinSpaces(space);
    
        b->displayWins(wins);
    
        if (0 < wins.count() || b->boardIsFull())  b->disableBoard();
    
        w->addCurrPlayerScore(wins.count());
    
        w->iteratePlayer();
    
        w->highlightCurrPlayer();
    }
    

    我已经尝试将PlayGameWindow的实例传递到每个Board实例中,以便Board类可以使用PlayGameWindow函数,但当调试器转到正确的PlayGameWindow功能时,当它尝试使用任何PlayGameWindow变量或对象时,它会分段,并且无法在调试器中查看PlayGameWindow实例信息。

    我曾尝试将PlayGameWindow函数或点击事件使用的函数作为朋友,但使用PlayGameWindow功能也会导致同样的问题。

    我曾尝试将函数作为lambda函数发送给稍后在click事件函数中调用,但这也带来了同样的问题。我不能在Board类中使用PlayGameWindow函数,即使它是公共的。

    我的最后一个办法是不再封装Board类,并将所有内容都放回PlayGameWindow类中,但我希望避免这种情况,因为Board功能从封装中受益。

    0 回复  |  直到 3 年前
        1
  •  1
  •   Mahendra Panpalia    3 年前

    从你的描述来看,你似乎很难定义两者之间的关系 PlayGameWindow Board 班访问类对象时遇到困难,表明存在设计问题。

    在典型的Qt应用程序中,小部件通常遵循父/子关系。在这种情况下,将PlayGameWindow作为父类,将Board作为子类是合适的。此外,标签应该是董事会的子公司。这种层次关系与应用程序的预期结构相一致。

    要从子类(Board)访问父类(PlayGameWindow),建议使用依赖注入,而不是依赖聚合(使父类成为子类的成员变量)。依赖项注入涉及将父对象作为参数传递给子类构造函数或特定方法,以确保子类具有对其父类的引用。

    您不应该使用父级(PlayGameWindow)作为子级(Board)的类成员。

    例如

    #include <QObject>
    #include <QWidget>
    #include <QGridLayout>
    #include <QPushButton>
    
    // Forward declaration of Board class
    class Board;
    
    class GameWindow : public QWidget {
        Q_OBJECT
    public:
        explicit GameWindow(QWidget* parent = nullptr);
        ~GameWindow();
    
    private slots:
        void createBoard();
    
    private:
        QGridLayout* layout;
        QPushButton* addButton;
        QList<Board*> boards;
    };
    
    class Board : public QWidget {
        Q_OBJECT
    public:
        explicit Board(GameWindow* parent = nullptr);
        ~Board();
    
    private slots:
        void spaceClicked();
    
    private:
        QGridLayout* layout;
        // Other member variables and functions related to the board
    };
    

    Board类有一个GameWindow*指针作为其父级。这建立了父子关系,其中GameWindow是父级,Board是子级。父子关系对于管理内存和确保删除父对象时进行正确的清理非常有用。

    注意:提供的代码是一个简化的示例,用于演示GameWindow和Board类之间的父子关系。您可能需要修改和扩展代码以适应您的特定应用程序要求。