C++では,構造体に「メンバ関数」というものを定義することができる. 例として,2次元のベクトルを考えてみよう.Cなら,こんな風に定義 するだろう.
デバッグのために,このベクトルを標準出力にプリントする関数を考えて みよう.Cなら,こんな風に書くところだ.struct vector2D { int x; int y; };
Cでは,他の構造体のprintと区別するため,例えばprint2D のような名前にするだろう. C++では,関数の多重定義があるので,もっと単純にvoid print2D(struct vector2D *v) { printf("(%d,%d)",v->x, v->y); }
でよい.しかし,できれば,構造体とそれを操作する 関数は組になっていた方がわかりやすい.そこで,C++では次のような 記述ができる.void print(vector2D *v) { printf("(%d,%d)",v->x, v->y); }
構造体のメンバとして,変数のほかに,構造体を扱う関数も 入れることができるというわけだ.これをメンバ関数という. 実際の構造体の中には,x, yのデータしか入っていないので, メンバ関数をたくさん追加しても,構造体の大きさが大きくなる 心配はない.メンバ関数を使うときには,次のようにする.struct vector2D { int x; int y; void print() { printf("(%d,%d)",x,y); } };
構造体が変数に入っている場合は,vector2D v; v.x = 10; v.y = 12; v.print();
変数名.メンバ関数名(引数)のように呼び出す.構造体へのポインタが変数に入っているときには, もちろん
変数名->メンバ関数(引数)になる.
メンバ関数の定義のなかでは,構造体のタグであるxとか yを,あたかも普通の変数のように扱うことができる. (Pascalを知っている人なら,with文を想像するとよい.) また,メンバ関数の中では,今扱っている構造体へのポインタを, thisという特殊な変数で指定することができる.だから, 上の記述は
と書いてもまったく同じだ.struct vector2D { ... void print() { printf("(%d,%d)",this->x,this->y); } };
複数のファイルで同じ構造体を使う場合,構造体の定義を ヘッダファイルに書く必要がある.その場合,メンバ関数はどうするのか というと,次のようにする.
ヘッダファイル
struct vector2D { int x; int y; void print(); };
本文
void vector2D::print() { printf("(%d,%d)",x,y); }
vector2D::printというのは,「vector2Dという構造体のメンバ であるprint」という意味だ.ヘッダファイルではメンバ関数の プロトタイプを宣言し,関数本体は別ファイルにするわけである. ただし,ヘッダファイルに関数本体を書いてもかまわない.この場合, ヘッダファイルに直接書かれた関数は,後述するインライン展開の対象 になる.