2012-09-18 21 views
0

所以情況如下:在C++中,轉換爲重載函數的子類?

我有一個抽象超類「模型」的光線追蹤程序,從中各種幾何形狀繼承屬性和功能。顯然不會有類型模型的對象,但是會有一個類型模型的數組,其中將存儲場景的整個幾何圖形。

然後一些光線將由光線追蹤器投射。每條射線將遍歷這個模型數組,並檢查它是否使用它自己的方法Ray :: intersect與它們碰撞。因此,Ray的聲明大致包括這樣的:

Point intersect(Sphere sphere) {...} 

Point intersect(Cube cube) {...} 

Point intersect(Torus torus) {...} 

問題是,因爲所有這些類從模型繼承,並且陣列是類型的模型,所述元件將是類型的模型的時候都訪問。模型沒有交集,所以我不會得到一個錯誤的方法錯誤,就像沒有這樣的方法錯誤一樣。所以問題是:我如何將每個成員轉換爲適當的類型?

是否有合理的方法來做到這一點,或者我必須爲每個對象明確地投射每個子類,並且使用任何支柱?這看起來似乎是一個常見問題,這似乎很駭人聽聞。

+1

如果你有一個從'Base'繼承的'Derived'類,爲什麼你不能只是做'Base :: Foo()'? –

+0

重載的方法用於接受超類型模型的對象的不同類。因此,一系列foo(bar [name]),foo(baz [name]),foo(biff [name])等函數,其中bar,baz和biff都從愚蠢的b字繼承而來抽象超類。 –

+0

這是經典的「雙派遣」或「多派遣」方案。它在文獻中有很好的記錄和寫作。 –

回答

1

你應該反過來做。而不是使用Point intersect(Sphere sphere)等的Ray,每個模型應具有如下功能:virtual Point intersect(const Ray& ray) const

PS。另外,確保你的數組是Model *或某種形式的智能指針的數組,否則你將會切割你的模型。

PPS。一個真正的光線追蹤器會找到一種方法來將它們的光線放在一起,所以你沒有太多的(虛擬)函數調用。

編輯:

另外,也可以轉換爲特定的模式,但使用它在這種情況下,會毀了OOP的煩躁,而導致一個醜陋的switch語句。例如,假設你有一個Model* model,你認爲它可能是一個Sphere*,那麼你可以這樣做:Sphere* sphere = dynamic_cast<Sphere*>(model);。如果model確實是Sphere*,則sphere現在將指向它,否則sphere將是NULL。國際海事組織,你應該儘量避免在幾乎所有情況下使用dynamic_cast;如果你發現你必須使用它,這通常表明你的設計混亂了(重新設計,或者如果你沒有時間,從錯誤中學習)。

+0

關於聚束的公平點,但這只是一個任務,而且是我們第一次設計的迭代。感謝您的提示:指針,我得出了與您相同的結論:一般問題。謝謝! –