在现代 C++ 游戏引擎中组织全局系统访问

Organizing a global system access in a modern-C++ game engine

首先,如果这个问题已经得到回答,请原谅,但我不能确定我的选择。

我正在开发 C++ 游戏引擎,我希望它符合现代标准。我以 OOP 方式编写它,并且我有一个名为 ENGINE 的主要 class。在其中,有几个 class 实例代表特定的子系统:WINDOWD3D11_RENDERER 等。我还有一个必须可用的日志系统 (LOGGER)到所有子系统。

现在,这种对记录器的全局访问给我带来了问题。我不确定我是否应该在 ENGINE class 之外将其声明为静态的,并具有一个 returns 对它的引用或在 ENGINE 内实例化它的功能,并使所有子系统指向它。

为了让您更好地理解我在说什么,我发布了这些场景的简化版本(考虑到我删除了很多无意义的功能)。

第一个解法:

class LOGGER {...};

LOGGER* GetLogger()
{
    static LOGGER Logger;
    return &Logger;
}

// Just one example.
class WINDOW
{
    void Function()
    {
        GetLogger()->Write();
    }
};

class ENGINE
{
private:
    WINDOW Window;
}

注意 Irrlicht 引擎是这样的:

class Printer
{
public:
    static void Write();
    static LOGGER* Logger;
};

并且可以这样全局访问:

os::Printer::Write();

第二种解法:

class LOGGER() {...};

// Same example.
class WINDOW
{
public:
    void Initialize(LOGGER* pLogger)
    {
        Logger = pLogger;
    }

    void Function()
    {
        Logger->Write();
    }

private:
    LOGGER* Logger;
};

class ENGINE
{
public:
    void Initialize()
    {
        Window.Initialize(&Logger);
    }

private:
    WINDOW Window;
    LOGGER Logger;
}

我不知道哪个是最好的解决方案,如果您能指出正确的解决方案,我会很高兴。提前谢谢你。

我认为这张图更能代表您的需求:

您的组件应该与日志无关,因为它们的功能不依赖于日志记录功能。这个功能应该委托给引擎。

引擎本身可以包含一个 Logger 组件,它处理实际的日志记录。

让我们看一些基本代码:

class Engine {
    private:
        Logger& mLogger;
        EngineComponent mComponents[10];
    public:
        Engine(Logger& logger):
            mLogger(logger) {
        }

        void addComponent(EngineComponent& c, int pos) {
            mComponents[pos] = c;
            c.setEngine(this);
        }

        void log(const std::string& message) {
            mLogger.write(message);
        }
}

class EngineComponent {
    private:
        Engine* mEngine;
    protected:
        EngineComponent() {}
    public:
        void setEngine(Engine* engine) {
            mEngine = engine;
        }

        void log(const std::string& message) {
            if (mEngine != NULL) {
                mEngine->log(message);
            }
        }
}

class Window : public EngineComponent {
    // add implementation
}

class D3d11Renderer : public EngineComponent {
    // add implementation
}

class Logger {
    protected:
        Logger() {}
}

class FileLogger : public Logger {
    // add implementation
}

希望对您有所帮助。