「メンバ変数はできる限りメンバ関数を通して使う」ように奨励しました。ですが、「メンバ変数の値を返すだけ」「メンバ変数の値を設定するだけ」という関数を作っても、その関数を呼ぶ時間が無駄な気がします。今回は、こういうときにピッタリな「アノ」機能が再登場します。
それでは、今回の要点です。
では、いってみましょう。
メンバ変数はメンバ関数を通して使うのが普通です。例えば、前々回の m_pnum というのもそうしていますね。こうすれば、変な要素を使われることがない上に、m_pnum の値を変えられてしまうこともありません。
もちろん、必ずそうしなくてはならないということではありませんが、そうした方がいい場合がほとんどというのが実際です。
ということで、前のクラスに次のようなメンバ関数を加えてみました。メモリの確保に成功したかどうかを返す関数と、配列の要素数を返す関数と、配列のサイズを返す関数の3つです。
// NULL マクロは stddef.h で定義されています #include <stddef.h> class CIntArray { // メンバ変数 private: int* m_pnum; // 動的配列 int m_nNumOf; // 配列の要素数 // その他の情報の取得 public: bool Success(); // メモリの確保が成功したか int NumOf(); // 配列の要素数 int SizeOf(); // 配列のサイズ // 他のメンバは省略します }; // メモリの確保が成功したか bool CIntArray::Success() { return m_pnum != NULL; } // 配列の要素数 int CIntArray::NumOf() { return m_nNumOf; } // 配列のサイズ int CIntArray::SizeOf() { return m_nNumOf * sizeof *m_pnum; } |
...えらくすっきりした関数ですね。(^ ^; プログラムの中の一服の清涼剤のような爽やかさを感じます。
しかし、関数というのはある場所に作られ、呼ぶたびに処理はそこに移動します。これには一瞬ですが時間が必要です。大きな処理なら気になりませんが、いくら何でもこれは無駄な気がします。
こういうときにはどうすればいいのでしたか? そうです。第1部第66章でやったインライン関数を使えばいいのです。
#include <stddef.h> class CIntArray { // メンバ変数 private: int* m_pnum; // 動的配列 int m_nNumOf; // 配列の要素数 // その他の情報の取得 public: bool Success(); // メモリの確保が成功したか int NumOf(); // 配列の要素数 int SizeOf(); // 配列のサイズ // 他のメンバは省略します }; // メモリの確保が成功したか inline bool CIntArray::Success() { return m_pnum != NULL; } // 配列の要素数 inline int CIntArray::NumOf() { return m_nNumOf; } // 配列のサイズ inline int CIntArray::SizeOf() { return m_nNumOf * sizeof *m_pnum; } |
inline はクラスの宣言の中では書かず、実装の方にしか書きません。
こうすれば、関数の中身は呼ばれるたびにそこに展開されます。処理がそこに埋め込まれるのです。これで、関数を呼ぶときの時間を気にしてメンバ変数を public にするという必要はなくなります。
そして、クラスではインライン関数をよく使います。なのでかは知りませんが、インライン関数にする特別な書式が用意されています。
#include <stddef.h> class CIntArray { // メンバ変数 private: int* m_pnum; // 動的配列 int m_nNumOf; // 配列の要素数 // その他の情報の取得 public: // メモリの確保が成功したか bool Success() { return m_pnum != NULL; } // 配列の要素数 int NumOf() { return m_nNumOf; } // 配列のサイズ int SizeOf() { return m_nNumOf * sizeof *m_pnum; } // 他のメンバは省略します }; |
何と、クラスの宣言の中で実装しています。こうすれば、メンバ関数は inline と書かなくてもインライン関数になってくれます。
「クラスの中で宣言して、いろんなファイルで使いたいときに関数の二重定義にならないの?」と思うかもしれません。が、第1部第70章で言ったように、「インライン関数は内部リンケージになるので、定義をヘッダファイルに書いて公開」します。これで構わないのです。
クラスの宣言をヘッダファイルに書くときは、インライン関数はヘッダファイルで実装します。クラス内で実装するときでも、クラス外で実装するときでも、どちらでもです。別のファイルにあったら、処理を埋め込みたくてもどんな処理を埋め込めばいいのかが分からないからですね。
では、今回の要点です。
次回は、この CIntArray クラスにひそむ大きな問題点について暴露します。そして、その解決を行っていこうと思います。
Last update was done on 2000.8.7
この講座の著作権はロベールが保有しています