|
|
Log In | Not a Member? |
Contact ADC |
| < 前ページ次ページ > |
Objective-C++では、C++コードとObjective-Cメソッドのどちらの言語からでもメソッドを呼び出すことができます。どちらの言語でも、オブジェクトのポインタは単なるポインタであるため、どこでも使用できます。たとえば、Objective-CオブジェクトのポインタをC++クラスのデータメンバとして含めることができ、C++オブジェクトのポインタをObjective-Cクラスのインスタンス変数として含めることができます。リスト 11-1にこれを示します。
リスト 11-1 C++とObjective-Cインスタンスをインスタンス変数として使用
/* Hello.mm |
* Compile with:g++ -x objective-c++ -framework Foundation Hello.mm -o hello |
*/ |
#import <Foundation/Foundation.h> |
class Hello { |
private: |
id _greeting_text; // NSStringを保持 |
public: |
Hello() { |
_greeting_text = @"Hello, world!"; |
} |
Hello(const char* greeting_text) { |
_greeting_text = [NSString stringWithUTF8String:greeting_text]; |
} |
void say_hello() { |
printf("%s\n", [_greeting_text UTF8String]); |
} |
}; |
@interface Greeting :NSObject { |
@private |
Hello *_hello; |
} |
- (id)init; |
- (void)dealloc; |
- (void)sayGreeting; |
- (void)sayGreeting:(Hello*)greeting; |
@end |
@implementation Greeting |
- (id)init { |
if (self = [super init]) { |
_hello = new Hello(); |
} |
return self; |
} |
- (void)dealloc { |
delete _hello; |
[super dealloc]; |
} |
- (void)sayGreeting { |
_hello->say_hello(); |
} |
- (void)sayGreeting:(Hello*)greeting { |
greeting->say_hello(); |
} |
@end |
int main() { |
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
Greeting *greeting = [[Greeting alloc] init]; |
[greeting sayGreeting]; // > Hello, world! |
Hello *hello = new Hello("Bonjour, monde!"); |
[greeting sayGreeting:hello]; // > Bonjour, monde! |
delete hello; |
[greeting release]; |
[pool release]; |
return 0; |
} |
Objective-CインターフェイスでC構造体を宣言できるように、Objective-CインターフェイスでC++クラスを宣言することもできます。C構造体と同様に、Objective-Cインターフェイスで定義したC++クラスは、Objective-Cのクラス内にネストされず、有効範囲がグローバルになります(これは、C++ではなく、標準Cにおいてネストされた構造体定義の有効範囲がファイル単位になるのと同等です)。
言語に応じてコードの条件定義が行えるように、Objective-C++コンパイラは、C++およびObjective-C言語標準で規定されている、(それぞれ)__cplusplusと__OBJC__プリプロセッサ定数の両方を定義します。
前述したように、Objective-C++ではObjective-CオブジェクトからC++クラスを継承できず、C++オブジェクトからObjective-Cクラスを継承することもできません。
class Base { /* ...*/ }; |
@interface ObjCClass:Base ...@end // エラー! |
class Derived:public ObjCClass ...// エラー! |
Objective-Cと異なり、C++のオブジェクトは静的に型定義されており、例外的なケースとして実行時にポリモーフィズムが利用できます。そのため、2つの言語のオブジェクトモデルは、直接的には互換性がありません。さらに、より根本的な要素として、メモリ内におけるObjective-CとC++オブジェクトのレイアウトは相互に互換性がありません。つまり、両言語に対して有効なオブジェクトインスタンスを作成するのは、一般的に不可能です。したがって、2つのタイプの階層を混合することはできません。
Objective-Cのクラス宣言の中で、C++クラスを宣言することはできます。次のように、コンパイラは、グローバルなネームスペースで宣言されたものとして、このようなクラスを処理します。
@interface Foo { |
class Bar { ...} // OK |
} |
@end |
Bar *barPtr; // OK |
Objective-Cでは、(Objective-C宣言の中で宣言されたかどうかに関係なく)C構造体をインスタンス変数として使用できます。
@interface Foo { |
struct CStruct { ...}; |
struct CStruct bigIvar; // OK |
} ... @end |
Objective-C++も同様に、C++クラスインスタンスをインスタンス変数として機能させることを目指しています。該当するC++クラス(およびそのスーパークラスすべて)が仮想メンバ関数を定義しないかぎり、これは可能です。仮想メンバ関数がある場合、当該C++クラスはObjective-Cのインスタンス変数として機能しません。
#import <Cocoa/Cocoa.h> |
struct Class0 { void foo(); }; |
struct Class1 { virtual void foo(); }; |
struct Class2 { Class2(int i, int j); }; |
@interface Foo :NSObject { |
Class0 class0; // OK |
Class1 class1; // エラー! |
Class1 *ptr; // OK―Fooのinitから'ptr = new Class1()'を呼び出し、 |
// Fooのdeallocから'delete ptr'を呼び出す |
Class2 class2; // 警告―コンストラクタを呼び出さない! |
... |
@end |
C++では、仮想関数を含むクラスの各インスタンスが、適切な仮想関数テーブルポインタを含む必要があります。しかし、Objective-CランタイムはC++オブジェクトモデルを知らないため、仮想関数テーブルポインタを初期化することができません。同様に、Objective-Cランタイムは、それらのオブジェクトのC++コンストラクタまたはデストラクタに対して呼び出しを発行できません。C++クラスにユーザ定義コのンストラクタやデストラクタがあっても、それらは呼び出されません。そのような場合、コンパイラは警告を発します。
Objective-Cには、ネストされたネームスペースという概念がありません。C++のネームスペースではObjective-Cクラスを宣言できず、Objective-Cクラスでネームスペースを宣言することもできません。
Objective-Cクラス、プロトコル、およびカテゴリはC++テンプレート内で宣言できず、C++テンプレートをObjective-Cクラス、プロトコル、またはカテゴリの有効範囲内で宣言することもできません。
しかし、Objective-Cクラスは、C++テンプレートのパラメータとして使用することが可能です。また、Objective-Cメッセージ式では、C++テンプレートのパラメータを(セレクタとしてではなく)レシーバまたはパラメータとして使用することもできます。
| < 前ページ次ページ > |
Last updated: 2007-10-31
|
Get information on Apple products.
Visit the Apple Store online or at retail locations. 1-800-MY-APPLE Copyright © 2007 Apple Inc. All rights reserved. | Terms of use | Privacy Notice |