[英]How Do I Box Disparate “Resource” Pointers for SDL2?
我想實現一個資源加載器,從概念上講,感覺就像SDL2中的所有資源都是一樣的; 完成后您需要釋放資源, SDL_Texture*
與SDL_DestroyTexture
, Mix_Music*
與Mix_FreeMusic
, Mix_Chunk*
與Mix_FreeChunk
, TTF_Font*
與TTF_CloseFont
。 所有這些變化都是“刪除器”function 的名稱,所以我想將這些全部裝箱,這樣我就不需要為每種類型的資源使用 4 個不同的 std::maps。
我已經實現了一個小型 class 來裝箱數據,但是在使用 generics 時我無法恢復類型。 具體來說,當我嘗試通過value.get<SDL_Texture*>()
將void*
轉換回SDL_Texture*
時,我得到“SDL_Texture* 是不完整的類型”
值框.h
// helper class used to box various pointers for sdl, like textures, chunks, fonts, etc
class ValueBox {
public:
std::function<void(void)> clean;
void* data;
ValueBox(void* data, std::function<void(void)> clean) : data(data), clean( std::move(clean) ) {}
~ValueBox() {
clean();
}
template<typename T>
T get() {
return dynamic_cast<T>(data);
}
};
如何實現 class 允許我將指針裝箱,以便我不需要加載器中的四個不同映射? (或者我正在做一些我不應該做的事情?)
dynamic_cast
僅在您從多態類型轉換為多態類型(或void*
)時才有意義。 多態類型是一個class
(或struct
,形式上也是一個類),它至少具有(可能繼承)一個虛擬 function。
您列出的所有類型都不是多態的(因為它們來自 C 庫,而 C 沒有虛函數)。 但即使它們是, void
本身也不是多態的,所以它無論如何也行不通。
此外,您必須dynamic_cast
到指針或引用,但由於上述原因,這並不重要。
由於您的所有資源都是指針,因此您可以 [ab] 使用std::unique_ptr
自動處理它們。 這是FILE *
和std::fopen
的示例:
using file_ptr = std::unique_ptr<FILE, std::integral_constant<decltype(&std::fclose), std::fclose>>;
int main()
{
file_ptr f(std::fopen("foo.txt", "rb")); // This is closed automatically.
}
但是,我不建議這樣做,因為它只適用於指針。 如果您遇到一種不是指針的新型資源,您將不得不以不同的方式管理它,從而使您的代碼不一致。
理論上,您可以編寫一個類似於std::unique_ptr
的 class ,它不僅限於指針,但是在我自己嘗試之后,我認為這不是很方便,也不值得付出努力。
我建議為每種資源編寫一個單獨的 class,使用以下模式:
class FilePtr
{
FILE* file = nullptr;
public:
FilePtr() {} // Optional
FilePtr(const char *filename, const char *mode) // Change parameters as needed.
{
file = std::fopen(filename, mode);
if (!file)
throw std::runtime_error("Can't open file!");
}
FilePtr(FilePtr &&other) noexcept : file(std::exchange(other.file, {})) {}
FilePtr &operator=(FilePtr other) noexcept
{
std::swap(file, other.file);
return *this;
}
~FilePtr()
{
if (file)
std::fclose(file);
)
[[nodiscard]] explicit operator bool() const {return bool(file);} // Optional.
// Add more functions as needed.
};
由於這些包裝器非常簡單,您可以輕松地為每種資源編寫它們。
擁有單獨的類還允許您向它們添加特定於資源的功能。
class 允許我將指針裝箱,這樣我就不需要加載器中的四個不同的映射?
我會使用不同的地圖。 這意味着您不需要在運行時驗證資源類型,這意味着少了一個故障點。
但無論映射的數量如何,您都可以從單個基類繼承包裝類,以減少代碼重復。
如果您使基礎多態,您將能夠將資源存儲在該基礎的shared_ptr
(或unique_ptr
s)的單個 map 中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.