2013-08-31 99 views
0

我想編寫使用SDL 2.0一個簡單的遊戲,它的結構看起來有點像這樣:如何指定析構函數的調用順序?

  • 級發動機,這將在其構造函數初始化SDL(SDL.Init()),調用SDL_QUIT( ),幷包含Window和Texture的實例。
  • class Texture - SDL_Texture *的包裝類。在創建時創建紋理,破壞析構函數中的紋理
  • class Window - SDL_Window的包裝類,在開始時創建SDL_Window *和SDL_Renderer *,在析構函數中刪除。現在

,據我所知,SDL_QUIT()卸載DLL,關閉所有的子系統等。如果我理解正確的話,那麼如果我叫SDL_QUIT()調用SDL_DestroyWindow(),SDL_DestroyRenderer()和SDL_DestroyTexture()可能沒有影響或導致錯誤,因爲系統已卸載以及DLL。

因此,我希望在調用SDL_Quit()之前,Engine中的Texture和Window被銷燬在Engine的析構函數中。

當我試圖模擬它的簡單類例如,我得到簡單LIFO響應:

ClassOne對象初始化

ClassTwo對象初始化

聚合對象初始化

聚合對象銷燬

ClassTwo物體d estroyed

ClassOne對象銷燬

而且這還不是我想要的。我設法使用指針和動態內存分配來解決我的問題。我只需在Aggregate的構造函數中使用operator new創建它們,並使用析構函數中的運算符delete將其銷燬。

但是,有沒有其他方式來做到這一點,不涉及指針? 在此先感謝。

+2

顯示您的實際代碼,並考慮使用一些[智能指針](http://en.wikipedia.org/wiki/Smart_pointer)。也許考慮使用[Boehm的垃圾收集器](http://www.hpl.hp.com/personal/Hans_Boehm/gc/)。 –

+0

對於'class Foo {public:Foo(){/ * hello * /}〜Foo(){/ * bye * /} private:A a; B b; };',當你創建一個'Foo'對象時,它總是會構造'a'(調用'A :: A()'),然後構造'b',然後執行'/ * hello * /' ;並且當對象被銷燬時,它總是會執行'/ * bye * /',然後銷燬'b',然後按照該順序銷燬'a'(調用'A ::〜A()')的建設)。因此,在您當前的設計中,您似乎遇到了破壞_and_構造的問題:您將嘗試創建SDL_Window和SDL_Texture _before_ SDL_Init()。 –

+0

@up噢,沒錯,沒有看到這個。所以我不得不使用指針? – MatthewRock

回答

2

不涉及指針:

如果您有(假設#include <iostream>

class Window { 
public: 
    Window() { std::cout << "W "; } 
    ~Window() { std::cout << "~W "; } 
}; 

class Texture { 
public: 
    Texture() { std::cout << "T "; } 
    ~Texture() { std::cout << "~T "; } 
}; 

,你想對應的,以輸出Init W T~T ~W Quit的話,而不是說:

class Engine { 
public: 
    Engine() { std::cout << "Init "; } 
    ~Engine() { std::cout << "Quit "; } 
private: 
    Window w; 
    Texture t; 
}; 

(其確實爲W T InitQuit ~T ~W),請執行此操作:

class Initializer { 
public: 
    Initializer() { std::cout << "Init "; } 
    ~Initializer() { std::cout << "Quit "; } 
}; 

class Engine { 
public: 
    Engine() { /* nothing */ } 
    ~Engine() { /* nothing */ } 
private: 
    Initializer i; 
    Window w; 
    Texture t; 
}; 
+1

或使用基類。 – dyp

+0

如果我有足夠的聲望,我會投票。這就是方式,非常感謝你!你一直是最有幫助的。 – MatthewRock

+0

@DyP通過「使用基類」,你的意思是'class Engine:private Initializer {...'(並且當然刪除成員'i')?即使用私有繼承而不是組合?如果是的話,這確實是一種選擇。 –

1

如果您訂購的類正確,你獲得期望的消滅順序:

在一個類中:在和破壞建築:

class X { 
    public: 
    X() 
    // This order is not relevant and should produce a compiler warning 
    : ..., c(), b(), a() 
    {} 


    private: 
    // The members are initialized in this order and destructed in the opposite order. 
    A a; 
    B b; 
    C c 
    ... 
} 

同樣適用於靜態實例在一個翻譯單元(!)按照定義的相反順序。

如果您有多個翻譯單元,則未指定每個單元初始化的順序。在函數中使用靜態數據可以簡化它 - 數據在第一個函數調用中被初始化。

+0

是的,我知道這一點。然而,我想在構造函數中初始化變量(在構造函數的末尾),並在析構函數的開始處銷燬它們 - 順序並不重要,它們只需在析構函數中銷燬即可。 – MatthewRock

+0

+1基本上釘牢所需的基本知識。 – sehe