【发布时间】:2021-10-19 16:22:56
【问题描述】:
背景:
我有一个游戏引擎,其中有多个 externed 全局指针指向各种子系统,以便下游游戏应用程序易于访问:
#pragma once
#include <type_traits>
class JobSystem;
class FileLogger;
class Renderer;
class Console;
class Config;
class UISystem;
class InputSystem;
class AudioSystem;
class EngineSubsystem;
class GameBase;
extern JobSystem* g_theJobSystem;
extern FileLogger* g_theFileLogger;
extern Renderer* g_theRenderer;
extern Console* g_theConsole;
extern Config* g_theConfig;
extern UISystem* g_theUISystem;
extern InputSystem* g_theInputSystem;
extern AudioSystem* g_theAudioSystem;
extern GameBase* g_theGame;
extern EngineSubsystem* g_theSubsystemHead;
template<typename GameDerived>
GameDerived* GetGameAs() noexcept {
static_assert(std::is_base_of_v<std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<GameBase>>>, std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<GameDerived>>>>);
return dynamic_cast<GameDerived*>(g_theGame);
}
问题:
我希望能够提供一个指向 App 类的全局指针,但该类是一个模板这一事实使得它难以理解如何实现它。
伪代码实现:
类层次结构:
#pragma once
#include <type_traits>
class GameBase { /*...*/ }
class Game : public GameBase { /*...*/ }
template<typename GameType>
class App {
static_assert(std::is_base_of_v<GameBase, GameType>, "Template type GameType not derived from GameBase.");
public:
static void CreateApp() {
if(_theApp) {
return;
}
_theApp = new App<T>();
}
static void DestroyApp() {
if(!_theApp) {
return;
}
delete _theApp;
_theApp = nullptr;
}
//...
private:
void SetupSubsystemPointers() {
//...
_theRenderer = std::make_unique<Renderer>();
g_theRenderer = _theRenderer.get();
//...
_theGame = std::make_unique<GameType>();
g_theGame = _theGame.get();
//...This does not work:
//g_theApp = this;
}
std::unique_ptr<JobSystem> _theJobSystem{};
std::unique_ptr<FileLogger> _theFileLogger{};
std::unique_ptr<Config> _theConfig{};
std::unique_ptr<Renderer> _theRenderer{};
std::unique_ptr<Console> _theConsole{};
std::unique_ptr<InputSystem> _theInputSystem{};
std::unique_ptr<UISystem> _theUI{};
std::unique_ptr<AudioSystem> _theAudioSystem{};
std::unique_ptr<GameType> _theGame{};
//I would really like this to be a std::unique_ptr.
static inline App<GameType>* _theApp{};
}
这是我在实现指向 App 类的全局指针时遇到的麻烦。
通用标题:
#pragma once
#include <type_traits>
class JobSystem;
class FileLogger;
class Renderer;
class Console;
class Config;
class UISystem;
class InputSystem;
class AudioSystem;
class EngineSubsystem;
class GameBase;
extern JobSystem* g_theJobSystem;
extern FileLogger* g_theFileLogger;
extern Renderer* g_theRenderer;
extern Console* g_theConsole;
extern Config* g_theConfig;
extern UISystem* g_theUISystem;
extern InputSystem* g_theInputSystem;
extern AudioSystem* g_theAudioSystem;
extern GameBase* g_theGame;
// WHAT DO I NEED TO DO TO GET SOMETHING LIKE THE FOLLOWING TO WORK?
//extern App* g_theApp;
//I tried
//template<typename GameType>
//App<GameType>* g_theApp but compilation failed with an undefined variable error or template vomit errors.
//extern GameType* g_theGame; //This would be nice to have. It would replace the above GameBase pointer and the below GetGameAs function
extern EngineSubsystem* g_theSubsystemHead;
template<typename GameDerived>
GameDerived* GetGameAs() noexcept {
static_assert(std::is_base_of_v<std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<GameBase>>>, std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<GameDerived>>>>);
return dynamic_cast<GameDerived*>(g_theGame);
}
常见实现:
#include "Engine/Core/EngineCommon.hpp"
JobSystem* g_theJobSystem = nullptr;
FileLogger* g_theFileLogger = nullptr;
Renderer* g_theRenderer = nullptr;
Console* g_theConsole = nullptr;
Config* g_theConfig = nullptr;
UISystem* g_theUISystem = nullptr;
InputSystem* g_theInputSystem = nullptr;
AudioSystem* g_theAudioSystem = nullptr;
GameBase* g_theGame = nullptr;
EngineSubsystem* g_theSubsystemHead = nullptr;
//DOES NOT WORK
//App* g_theApp = nullptr;
【问题讨论】:
-
template<typename GameType> App<GameType>* g_theApp应该可以工作。看起来您忘记在公共标头中转发声明App。 -
另外,如果您支持 C++17,您可以将所有这些外部变量改为内联变量,这样您就可以在头文件中定义它们。
-
那些不透明的前向声明类是怎么回事?为什么不包括相关的类定义?另外,为什么你需要它们全局?它们似乎属于 App 类。
-
@SergeyA 全局访问,供下游游戏直接使用。 App 类只管理它们的生命周期。
-
@NathanOliver 将您的评论作为答案,我会接受。
标签: c++ pointers templates global-variables extern