2010-05-22 60 views
2

我對C++相當陌生,但已經與C#合作了多年,但它並沒有幫助我。 :)在C++中鑄造派生類型問題

我的問題:我有一個ActorBallPeg都來自我正在從事的Objective-C iphone遊戲。在測試碰撞時,我希望根據actorAactorB的實際運行時類型適當設置BallPeg的實例。我的代碼,測試此如下:

// Actors that collided 
     Actor *actorA = (Actor*) bodyA->GetUserData(); 
     Actor *actorB = (Actor*) bodyB->GetUserData(); 

     Ball* ball; 
     Peg* peg; 
     if (static_cast<Ball*> (actorA)) { // true 
      ball = static_cast<Ball*> (actorA); 
     } 
     else if (static_cast<Ball*> (actorB)) { 
      ball = static_cast<Ball*> (actorB); 
     } 
     if (static_cast<Peg*> (actorA)) { // also true?! 
      peg = static_cast<Peg*> (actorA); 
     } 
     else if (static_cast<Peg*> (actorB)) { 
      peg = static_cast<Peg*> (actorB); 
     } 
     if (peg != NULL) { 
      [peg hitByBall]; 
     } 

一旦ballpeg被設置,然後我繼續運行hitByBall方法(目標C)。

我的問題真的在於鑄造程序中,BallactorA中投下了罰款;第一個if (static_cast<>)語句適當地介入並設置ball指針。

第二步是將相應的類型分配給peg。我知道peg應該是一個Peg類型,我以前知道它會是actorB,但是在運行時,檢測類型,我很驚訝地發現實際上第三個if (static_cast<>)聲明介入並設置此,如果聲明是檢查actorA是一個Peg,我們已經知道actorABall!爲什麼它會在這裏而不是在第四個if聲明?

我可以承擔的唯一的事情是如何鑄造從C#的工作方式不同,那就是它發現actorA這實際上是Ball類型從Actor派生,那麼它的時候發現static_cast<Peg*> (actorA)執行它發現PegActor派生太多,所以這是一個有效的測試?這可能都歸結爲我誤解了static_cast的使用。我怎樣才能達到我需要的? :)

我真的很擔心我的感覺像一個漫長的蠻力鑄造嘗試在這裏與一噸荒謬的if聲明。我敢肯定,有一種更簡單的方法可以實現簡單的轉換爲Peg,並根據actorAactorB中保存的實際類型轉換爲Ball

希望有人能幫助! :) 非常感謝。

+0

什麼是GetUserData的返回類型() ? – Marlon 2010-05-22 04:20:49

+0

這將是一個'球'或'釘'。它可以改變。 – GONeale 2010-05-22 04:37:36

+0

'static_cast'不能像那樣工作。您錯誤地將'static_cast'作爲'dynamic_cast'。 – sellibitze 2010-05-22 07:13:21

回答

3

由於這是Objective-C代碼(不是C++,按照標題),爲什麼不直接叫:

[actorA hitByBall]; 
[actorB hitByBall]; 

更新時間:如果您要發送消息的對象是nil它會被忽略。如果發送消息的對象沒有實現hitByBall,除非在基類中放入了一個空的定義(Actor),否則會得到一個異常「selector not recognized」。

然後,您可以刪除ballpeg聲明以及所有static_cast(即使在C++中也是不正確的)。

+0

謝謝瓊斯。在重新思考我的實現之後,正如許多人所建議的,我同意你的看法,經過多一點研究並意識到所有客觀c方法都是有效的'虛擬',那麼我可以簡單地不實現基本方法,是的,就像你說的那樣,只是實現一個hitByBall對於Peg和其他班級將無視。謝謝。 – GONeale 2010-05-22 06:44:15

+0

這在一般情況下並不正確。如果一個對象沒有實現一個方法,你會得到一個選擇器未被識別的異常。你可能都在談論的是重寫基類的實現。 – JeremyP 2010-05-22 14:45:43

+0

謝謝@JeremyP:我相應地澄清了我的答案。 – Johnsyweb 2010-05-23 00:27:54

2

要在運行時識別對象類型,您應該使用dynamic_cast而不是static_cast。但是你應該真的重新考慮你的設計。可能(我沒有任何關於objective-c的內容),你應該在基類中使hitByBall成爲一個虛擬方法,並且如果派生類需要,可以重寫實現。然後你可以調用該方法而不需要任何強制轉換。

+0

error:can not dynamic_cast'actorA'(類型'struct Actor *')鍵入'struct Ball *'(源類型不是多態) – GONeale 2010-05-22 04:18:22

+0

你可以發佈struct A和struct Ball的聲明嗎? – Naveen 2010-05-22 04:24:24

+0

「不要在測試代碼中使用dynamic_cast,如果您需要在運行時以單元測試的方式瞭解類型信息,那麼您可能會遇到設計缺陷。」 - 谷歌,支持你的建議重新考慮設計 – Marlon 2010-05-22 04:26:43

1

看來您在尋找-isKindOfClass。如果兩個對象符合NSObject的協議,你只需要檢查哪個是哪個類型的 - 實際的消息傳遞不是由靜態型指針的限制:

if ( [actorA isKindOfClass:[Peg class ]] 
    && [actorB isKindOfClass:[Ball class]]) 
{ 
    [actorA hitByBall]; 
} 
else if ( [actorB isKindOfClass:[Peg class ]] 
     && [actorA isKindOfClass:[Ball class]]) 
{ 
    [actorB hitByBall]; 
} 
+0

好吧,它們都在它們的根級繼承NSObject,非常好。我確實考慮過這個問題,但是我認爲,由於某種原因,我堅持使用C++類型測試之後,我再也沒有回過頭來。 – GONeale 2010-05-22 06:41:52