2012-05-11 4 views
11

Objective-Cに相当するC++のdynamic_castはありますか?Objective-C dynamic_cast?

は、それは、これを使用して偽造することができます。

MyClass *safeObject = [object isKindOfClass: [MyClass class]] 
         ? (MyClass *)originalObject : nil; 

しかし、私は多くの場合、それを入力する必要がない場合でも、これは、入力するためのコードがたくさんあります。

私は、これはかなり右ではないかもしれません少しさびが、私はC++で同等のだろうと信じて:

MyClass safeObject = dynamic_cast<MyClass>(orginalObject); 

ここコンテキストはパラメータはのタイプとして定義されているブロックでありますより一般的なクラスですが、このブロックでは、それが特定のサブクラスであることを「知っています」。それにもかかわらず、私は(MyClass *)originalObjectで盲目的にキャストし、理論的に考えられるエラーを無視したくありません。

私はdynamic_castが大好きですが、このケースも安全に対処するための代替アプローチがあれば幸いです。

+0

最悪の場合、このためのマクロを書くことができます。 – JustSid

+4

Objective-Cはダックタイプです。かなり正直なところ、「複雑な」キャストは言語に対してちょっとしたローミングです。 – zneak

+0

はい、おそらくここで間違った質問をしたと思っています。私が*質問しなければならない質問には、とにかくそれを期待していないので、NSAssert([object isKindOfClass:[MyClass class]]、@ "blahblah")の答えがありました。 :) –

答えて

15

#define objc_dynamic_cast(obj, cls) \ 
    ([obj isKindOfClass:(Class)objc_getClass(#cls)] ? (cls *)obj : NULL) 

#include <objc/runtime.h> 

することを忘れないでくださいは次のようにそれを使用します-C++では、これを簡単に書くことができます:

template<typename T> inline T* objc_cast(id from) { 
    if ([from isKindOfClass:[T class]]) { 
     return static_cast<T*>(from); 
    } 
    return nil; 
} 

これは、obj-cオブジェクトを除いて、正確にdynamic_cast<>のように動作するはずです。


あなたはバニラのObj-Cに固執する場合は、NSObject上のクラスのメソッドと同様の動作を得ることができます:

@interface NSObject (Cast) 
+ (instancetype)cast:(id)from; 
@end 

@implementation NSObject (Cast) 
+ (instancetype)cast:(id)from { 
    if ([from isKindOfClass:self]) { 
     return from; 
    } 
    return nil; 
} 
@end 

あなたがする必要があるため、このバージョンは、単に使用するように素敵ではありません

UIButton *button = [UIButton cast:someView]; 

キャストが失敗した場合、結果の値はnilです。

+0

この2番目の例は、私が探していたものです。そして素晴らしくシンプルなもの。ありがとうございました。 –

+0

これはinstancetype演算子を使いやすいので、コンパイラとXcodeのオートコンプリートは変換された型の使用を直ちに開始できます – SystematicFrank

3
  1. ありそうもありません。
  2. 私はバグのためのスペースがここではかなり小さいと思います。
  3. しかし、あなたが主張すれば、マクロはうまくいくでしょうか?
7

このマクロを試してください:あなたが目的を使用して喜んでいる場合

MyClass *safeObject = objc_dynamic_cast(originalObject, MyClass); 
+0

私はあなたが気にしないことを願っていますが、私はあなたのマクロをラップし、コンパイラの警告を満たすために(cls *)を追加しました。よくやった!私はXcodeの編集範囲のためにここでマクロを使用することを躊躇しましたが、それは素晴らしく機能するようです。 –

+0

このマクロの使用方法を示す行を追加してください(より環境に優しい外部者用)。ありがとう。 – Wienke

+0

私は1つを追加しました。 (H2CO3:あなたの答えがうんざりしていると感じたら、元に戻すことをお勧めします) –