2012-10-20 132 views
0

我正在研究一個簡單的圖形引擎,並且我有Drawable對象,在創建時(在構造函數中),它們應該將自己註冊到Renderer(通過將它們插入集合中)。它們還需要進行排序(通過透明度,深度遮罩等),即它們需要通過一些布爾標誌進行排序。std :: set的有效比較函數

所以這裏是我的設置。

std::set<Drawable *, DrawableComp> drawable_set; 

比較函子:中可繪製

struct DrawableComp : public std::binary_function<const Drawable *, const Drawable *, bool> { 
    bool operator() (const Drawable * lhs, const Drawable * rhs) const 
    { 
     return *lhs < *rhs; 
    } 
}; 

和重載操作<:

bool Drawable::operator<(const Drawable & rhs) const 
{ 
    if (writesDepth() != rhs.writesDepth()) 
     return !writesDepth() < !rhs.writesDepth(); 
    else 
     return getSortNumber() < rhs.getSortNumber(); 
} 

注意,這應該可繪製插入的順序設置,這樣第一次去那個寫對象到深度緩衝區,然後是那些不寫入深度緩衝區的深度緩衝區。排序號碼對每個對象都是唯一的。

問題是,這是行不通的。我在Draw集合的末尾寫入深度緩衝區的Drawables。

此外,writeDepth()是虛擬布爾函數。 Drawable只是一個抽象接口。如果我寫writeDepth()純虛擬,我得到運行時錯誤「純虛方法調用」。我不清楚爲什麼會這樣,因爲我從來沒有將Drawable對象設置爲集合,而是將其具體實現。

+0

只要您創建'writesDepth()'pure,就會得到_pure虛擬方法called_,這一事實表明至少有一個派生類不會覆蓋方法。這可能是導致排序順序錯誤的原因(派生類的所有實例將被錯誤地排序,因爲它們的writesDepth()方法不存在,因此會退回到返回錯誤值的基類方法)。那可能嗎? – jogojapan

+0

這不是我想的。我嘗試了打印和放置斷點。我有兩個Drawable實現。 writeDepth()實現和Drawable接口被調用。 –

+1

接口的'writeDepth()'也被調用?然後,無論是從派生類中調用它(是嗎?),或者必須至少有一個派生實現不能正確覆蓋它。你可以爲這兩個派生類發佈'writeDepth()'的代碼嗎?也許他們沒有被正確覆蓋。 – jogojapan

回答

0

好吧,我發現問題了。我正在從Drawable構造函數註冊Drawables。我在構造函數中調用這個(registerDrawable剛剛插入到集):

Application::get().getRenderer().registerDrawable(this); 

問題是,這將指向對象類型可繪製,而一些派生類型,所以設置「不知道」類是什麼派生它只是調用基本方法writeDepth()。

簡單的解決方案是將此調用移至派生構造函數。儘管它在我的設計中插入了一些亂七八糟的冗餘......

+0

這就是這裏沒有發生什麼 - 發生的事情是,當基類正在被初始化時,你正在調用'writeDepth()'函數,這意味着它仍然是基類類型的對象,而不是派生類的類型。 –

+0

感謝您的澄清。你有沒有關於設計的建議,所以我可以自動註冊Drawable,而不必在每個派生構造函數中做這些事情? –

相關問題