W.I.S. Laboratory
menu-bar

C


C言語の構造体にアクセサメソッドを追加してみる(意味なし)

Cの構造体にゲッターメソッドとセッターメソッドをくっつけてみた。
C構造体のメンバは年中publicなので、まったく実用価値は無いが、C++やJavaのような「obj.get_val()」に似た記述がCでもできる。

C++のメンバ関数やJavaのメソッドは、関数内から自分が所属するインスタンス「this」が見えるので、インスタンス内の他のメンバやフィールドにアクセスすることができる。
しかしCの場合、関数は構造体メンバの関数ポインタによって紐づいているだけであり「メンバ関数」ではないので、自分が紐づいている元の構造体が見えない。
なので、呼び出し元から逐一構造体へのポインタを渡す必要がある。

これはRustやGoの方式と同じだ。
RustもGoも、インスタンスと関数(メソッド)が紐づいているだけで、関数(メソッド)がインスタンスの中に入っているわけではない。
どちらもメソッドチェーン(hoge.fugafunc() みたいなの)でメソッド呼び出しができるが、これは「hogeの中のfugafunc()」という意味ではない。
Rustの場合は第1引数にインスタンス変数を取るのだが、このインスタンス変数をD言語のようにメソッド名の前に置くことができるため、メソッドチェーンによる記述が可能になっている。
なので呼び出し先のメソッドでは第1仮引数を「&self(または&mut self)」としてポインタや参照を受け取る必要がある。
Goの場合はインスタンス(またはインスタンスへのポインタ)が特殊引数になっていて、これを仮引数・実引数共に関数の前に書くことでメソッドチェーン記述が可能になっている。

Cの場合はメソッドチェーンで書けるからといって、構造体へのポインタが関数に渡るわけではない。
Cには「関数の前に書いた変数が第1引数になる」というD言語のような仕様は無いので、構造体へのポインタは改めて引数として関数へ渡す必要がある。
なのでどうしても「hoge.fugafunc(&hoge)」みたいになる。
とはいえ、このテクニックを使うとCの関数名(というか呼び出し名)をスコープの中に押し込むことができる。
Cは名前空間を分割できないので名前衝突を回避するために関数名が長くなってしまいがちだが、そんな長くなってしまった関数の名前を少しでも短くして呼び出したいというときには役に立つかもしれない。


[ 戻る ]
saluteweb