はじめに
Objective-Cでは変数の定義時に*をクラス(型)ではなく変数に寄せる慣習がある
NSObject *object;
次のようにクラスに寄せるようなコードは最近では滅多に見ることがない
NSObject* object;
C/C++ではObjective-Cとは逆で、後者のようにクラス(型)側に寄せられることが多いのではないかと思う。
想像
なんでこんなになってるのか
Objective-Cではポインタを宣言時にあまり意識しない
この理由として想像するのは、Objective-Cのオブジェクトについてはポインタを意識することを最小限にしており、インスタンスとプリミティブな変数または構造体を宣言時に見分けやすくなっている
ABRect *abRect; //何かしらのインスタンスだろうなと推測する
CGRect rect; //プリミティブな型か構造体だろうなと推測する
Objective-Cでポインタ(というかアドレス)を意識する場面は最小限とは言うものの、関数の引数にインスタンスのアドレスを渡し、関数内の処理によりそのインスタンスをどうにかする場面はある。
ちなみに、上記の例のABRectクラスに*を付けない場合はコンパイルエラーとなる。
Interface type cannot be statically allocated
Objective-Cではクラスのインスタンスは*を付け、ヒープ領域に作られる方法でしか利用できない。
C++のメソッド定義などの事情
C++ではメンバ関数の宣言にクラス名自体を含み、関数名を::で繋ぐため、*を付ける位置がクラスでないと違和感が生じてしまう。
具体例を挙げると、C++のDropクラスの関数createがCCObjectを返す場合を考える
CCObject *Drop::create(); //ポインタがDropに対して影響を及ぼすように見える
CCObject* Drop::create(); //CCObjectのポインタを返すことが伝わる
よってメンバ関数において*はクラス名に付いている方が自然であり、変数の定義時も同じように統一されているように理解できる。
Objective-C++の内部でC++のコードを書くときのTips
あくまで自分のTipsですが、Objective-C++にC++が混在するソースコード中では次の自己満足ルールが良さそう
- Objective-Cのインスタンスを定義する際には*を変数側に寄せ
- C++のインスタンスを定義する際にはクラス側に寄せる
- (void)example
{
NSObject *hoge; // Objective-Cでhogeの定義
std::string* piyo; // C++でpiyoの定義
}
とか思ってみたがFacebookのC++を利用したライブラリpopではObjective-Cのような*の位置になっていますな...
Vector *Vector::new_vector(NSUInteger count, const CGFloat *values)
まとめ
- Objective-Cでは*の位置でそれ自体がObjectかどうかを見分け易い(型の情報ではないということを示したい)
- C++ではメソッド定義などの関係上、クラス(型)のすぐ後ろに*が付いているほうが自然に見える
- Objective-C++でC++が混在した環境ではそれぞれの形にしたら見分けがつけやすそうだがFacebook社はそのようにしていない