You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决C++类循环引用报错及栈对象跨类调用方法问题

问题解决:循环引用与类设计修正

问题根源

  1. 循环引用:MultiLauncher.h 和 keyEvents.h 互相包含,导致编译时无法解析类定义。
  2. 错误继承关系:keyEvents 继承 MultiLauncher,但 MultiLauncher 又包含 keyEvents 实例,触发无限递归构造,完全违背逻辑(按键事件类不该是主程序类的子类)。
  3. 静态方法调用非静态成员:processKey 是静态方法,无法直接调用 MultiLauncher 的非静态 exit() 方法,静态方法没有实例上下文支撑。

解决步骤

  1. 用前向声明替代头文件互相包含,消除循环引用。
  2. 修正类依赖:keyEvents 通过构造函数接收 MultiLauncher 的引用(避免指针/堆内存),而非继承。
  3. 调整GLFW回调逻辑:通过窗口用户指针传递 MultiLauncher 实例,让回调能访问到正确的对象。
  4. 将 processKey 改为非静态方法,绑定到具体的 MultiLauncher 实例。

修改后的代码

MultiLauncher.h

#pragma once
#include <fstream>
#include <sstream>
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include "defines.h"
#include "readFile.h"
#include "createShader.h"
#include "figure.h"

// 前向声明keyEvents,替代直接包含头文件
class keyEvents;

class MultiLauncher
{
public:
    MultiLauncher();
    ~MultiLauncher();

private:
    uint windowWidth;
    uint windowHeight;
    const char* windowName;
    bool keepRunningGame = 1;

    keyEvents keyEventsInstance;  // 栈对象,符合需求

private:
    static void callback(GLFWwindow* window, unsigned int codepoint);

public:
    int run();
    GLFWwindow* initApp();
    void exit();
};

MultiLauncher.cpp

#include "MultiLauncher.h"
#include "keyEvents.h"  // 在cpp文件中包含头文件,补充类定义

MultiLauncher::MultiLauncher() :
    windowWidth(WINDOW_DEFAULT_WIDTH), windowHeight(WINDOW_DEFAULT_HEIGHT), windowName(WINDOW_DEFAULT_NAME),
    keyEventsInstance(*this)  // 初始化keyEvents时传递当前实例的引用
{

}
MultiLauncher::~MultiLauncher()
{

}

int MultiLauncher::run()
{
    std::cout << "Begin..." << std::endl;
    GLFWwindow* window = initApp();
    // 将当前MultiLauncher实例绑定到窗口用户指针
    glfwSetWindowUserPointer(window, this);
    glfwSetCharCallback(window, callback);

    figure triangle;

    while (!glfwWindowShouldClose(window) && keepRunningGame)
    {
        glClear(GL_COLOR_BUFFER_BIT);
        triangle.buildFigure();
        triangle.drawFigure();

        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    glfwTerminate();
    return 0;
}

GLFWwindow* MultiLauncher::initApp()
{
    if (glfwInit() != 1)
    {
        std::cout << "GLFW failed to initialize\n";
        std::cin.get();
    }

    GLFWwindow* window = glfwCreateWindow(WINDOW_DEFAULT_WIDTH, WINDOW_DEFAULT_HEIGHT, WINDOW_DEFAULT_NAME, glfwGetPrimaryMonitor(), NULL);
    if (!window)
        glfwTerminate();

    glfwMakeContextCurrent(window);

    if (glewInit() != GLEW_OK)
    {
        std::cout << "GLEW failed to initialize\n";
        std::cin.get();
    }
    return window;
}

void MultiLauncher::exit()
{
    keepRunningGame = 0;
}

void MultiLauncher::callback(GLFWwindow* window, unsigned int codepoint)
{
    std::cout << codepoint << std::endl;
    // 从窗口用户指针取出MultiLauncher实例
    MultiLauncher* launcher = static_cast<MultiLauncher*>(glfwGetWindowUserPointer(window));
    // 调用实例的keyEvents处理方法
    launcher->keyEventsInstance.processKey(codepoint);
}

keyEvents.h

#pragma once
#include "defines.h"

// 前向声明MultiLauncher,避免循环包含
class MultiLauncher;

class keyEvents
{
public:
    keyEvents(MultiLauncher& launcher);
    ~keyEvents();

    // 改为非静态方法,绑定到具体的MultiLauncher实例
    void processKey(uint key);

private:
    MultiLauncher& m_launcher;  // 用引用持有主程序实例,避免指针/堆内存
};

keyEvents.cpp

#include "keyEvents.h"
#include "MultiLauncher.h"  // 在cpp文件中包含头文件,补充类定义

keyEvents::keyEvents(MultiLauncher& launcher) : m_launcher(launcher)
{}

keyEvents::~keyEvents()
{}

void keyEvents::processKey(uint key)
{
    if (key == 27)  // Escape键ASCII码为27,修正原代码的错误(97是字母a)
        m_launcher.exit();  // 通过引用调用主程序的退出方法
}

内容的提问来源于stack exchange,提问作者LondonNight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 21:40:59