簡體   English   中英

如何為 SDL2 裝箱不同的“資源”指針?

[英]How Do I Box Disparate “Resource” Pointers for SDL2?

我想實現一個資源加載器,從概念上講,感覺就像SDL2中的所有資源都是一樣的; 完成后您需要釋放資源, SDL_Texture*SDL_DestroyTextureMix_Music*Mix_FreeMusicMix_Chunk*Mix_FreeChunkTTF_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM