2009-06-29 8 views
5

Objective-CとC++を混在させる必要があります。私はすべてのC + +のものを1つのクラスの中に隠して、他のすべてのクラスをObjective-Cに明示します。問題は、インスタンス変数としてC++クラスをいくつか使いたいということです。つまり、ヘッダーファイルに記述する必要があります。ヘッダーファイルは他のクラスに含まれており、C++はアプリケーション全体に広がり始めます。私が今までにできる最善の解決策は次のようなものです:Objective-Cクラスのインスタンス変数としてのC++クラス

これは機能します。実装ファイルはmmという拡張子を持ち、Objective-CとC++を混在させてコンパイルします。#ifdefはC++のロックを解除します。他の純粋にObjective-Cクラスがヘッダーをインポートすると、C++のものは隠され、クラスは特別なものを見ません。これはハックのように見えますが、より良い解決策がありますか?

+1

それは私が、私は同じ問題を抱えていたときに出ているものを基本的にです:

は、より詳細かつ++にObjCについて長々と語るポッドキャストなどの情報へのさらなるリンク、このスレッドを参照してください。しかしifdefに注意してください。非cppブランチのためにパディングを挿入する必要があります。それ以外の場合、コンパイラはあなたのFooオブジェクトのサイズを知りません。これは非壊れやすいインスタンスvarビルドでは破らないかもしれませんが、古いスタイルのターゲットでは間違いなく問題です。 –

+0

上記のアプローチをコピーしました。かなり素晴らしく簡単でしたが、それはいくつかの狂ったメモリ破損の問題を引き起こしました:http://stackoverflow.com/questions/2458652/objective-c-insanity-simple-assignement-to-a-single-float-variable-results – morgancodes

答えて

8

これは、インターフェイス/ @プロトコルの古典的な使い方のようです。 APIのobjective-cプロトコルを定義し、Objective-C++クラスを使用してそのプロトコルの実装を提供します。この方法では、クライアントは実装のヘッダーではなくプロトコルについて知る必要があります。だから私は、プロトコル

//Extending the NSObject protocol gives the NSObject 
// protocol methods. If not all implementations are 
// descended from NSObject, skip this. 
@protocol IFoo <NSObject> 

// Foo methods here 
@end 

を定義し、元Foo宣言

@interface Foo : NSObject <IFoo> 
{ 
    id regularObjectiveCProperty; 
    CPPClass cppStuff; 
} 

@end 

へのクライアントコードを変更します元の実装

@interface Foo : NSObject 
{ 
    id regularObjectiveCProperty; 
    CPPClass cppStuff; 

} 

@end 

を与え、その後タイプid<IFoo>で動作することができますし、必要はありませんObjective-C++としてコンパイルされます。明らかに、これらのクライアントにFooのインスタンスを渡すことができます。

+0

@interface Fooが.hファイルにある場合、obj-C++の影響を防ぐことが可能ですか? @interface Fooが.mmファイルにある場合、どうすればそのインスタンスを作成できますか? – Eonil

+1

Foo.hをインポートするモジュールはObjective-C++としてコンパイルする必要がありますが、クライアントコードではIFooを使用するためにimport * only * IFooのヘッダーが必要でObjective-Cのみが必要です。これは古典的な依存関係管理パターンです。あなたの例で –

+0

、ヘッダーをインポートせずに新しいFooをどのようにインスタンス化するのでしょうか?最初に頭に浮かぶのはObjective C++のファクトリクラスで、ヘッダにはインポートやC++の処理が含まれていません。それはすべて非常に複雑に思えます。このアプローチもあります:http://stackoverflow.com/questions/2262011/adding-c-object-to-objective-c-class/2262395しかし、私はそれを働かせていません(http://stackoverflow.com参照)/question/2463970/trouble-using-opaque-pointer-in-objective-c) – morgancodes

1

Objective C++をすべて使用することができない特別な理由はありますか?コンパイラをソースとしてコンパイルするだけです:Objective C++(または.cppまたは.mからすべてのソースファイルの名前を.mmに変更)。そして、あなたは自由に何の問題がそれであり、あなたのC++とObjective Cの全体 アプリケーション

に拡散し始め++

Cを混在できますか?あなたのObjective CコードがC/Objective Cコードだけを一般的に実行している場合、C++としてコンパイルされてもほとんど影響を受けません。相当なサイズや速度の問題はありません。

私が見つけた唯一の2つの欠点は次のとおりです。あなたは(まだ)analyseC++にclangスタティックアナライザーを使用できません。いくつかの(比較的奇妙な)CコードはC++で動作しません。これは、サードパーティ製のCコードを使用するときに問題となることがあります。

+0

唯一の問題は、私がC++に慣れていないことと、いくつかの微妙な違いバグにつながる可能性があります。私はC++が本当に必要なクラスにカプセル化されているという考えが好きです。しかし、ありがとう、これは確かに解決策です。 – zoul

0

ObjectiveC++の覚えていることから、あなたの囲まれたC++オブジェクトのコンストラクタとデストラクタが呼び出されないことがわかります。

3

最近この問題も発生しました。私の場合、プロトコルは過度のものでした。私はちょうどC++オブジェクトであったデータアクセスオブジェクトへのポインタを保持する必要がありました。

私がしたのは、void *インスタンス変数を持つクラスを宣言し、インスタンスメソッドで使用するときにキャストしました。

これは少しハックしますが、概念的にはObjective-C idのタイプと非常に似ています。あなたはこのクラスのための2つの別々のインスタンス変数のレイアウトを与えるインスタンス変数を、アウトIFDEF場合

0

この

をしないでください。ケースの半分でオブジェクトに割り当てられたメモリが短すぎるため、ランダムなメモリスマッシャが全面的に取得されます。代わりに、インスタンス変数をifdefingの、あなたのinit/deallocメソッドは新しい呼び出しに続い/オブジェクトを作成するには、削除、

struct CPPClass; 

のようにその型を前進宣言しIVARで、それへのポインタを持っています。いくつかのオブジェクトがある場合は、すべてのC++ ivarsを直接保持する構造体を作成し、その構造体を新規/削除するだけです。 Can I separate C++ main function and classes from Objective-C and/or C routines at compile and link?

+0

Cでは、struct型は 'CPPClass'ではなく' struct CPPClass'と呼ばれなければならないので、それを変更しなければなりません。 – newacct

+0

ivar宣言では、ええ、良いキャッチ。 C++のstruct FooとFooは同じですが、ヘッダーにのみ必要です。通常は、クラス名の前に構造体を書くのはどこでも使用しますが、ここで述べたように別の構造体宣言は必要ありません。 – uliwitness