C/C++ 振る舞いを動的に変化する [開発環境]
voidポインタ
- void ポインタにはほとんどのポインタをキャストなしで代入できる。
- void ポインタからは直接参照できない。
- void ポインタから他のポインタへの代入にはキャストが必要。
- void ポインタは型を不問でアドレスを受け取る引数に使う。
関数ポインタ
関数ポインタは、アドレスを格納する関数と同じ戻り値の型のポインタ変数を用意します。
仮引数がある場合は、続けて仮引数も指定します。
宣言時には、優先順位の関係から必ずポインタ名に ( ) をつけます。
型 (*変数名) (仮引数);
関数のエントリポイントをポインタに格納すれば、このポインタから関数を呼び出せます。
こうすることで、間接参照で関数を呼び出しすることができるのです。
関数のポインタで注目するべきは、間接参照であることです。
ポインタに関数のアドレスを代入できるというのは、非常に斬新なことです。
これまで、関数を呼び出すには直接関数名を指定する以外にありませんでした
しかし、間接参照することで関数の配列を実現することができます。
関数の配列がどれだけ斬新なものかは想像がつくでしょう。
この機能によって、プログラムの実行時に直接実行する関数を指定することができます。
しかも、非常に簡易にです。
#include <stdio.h> void kitty(void); void sakura(void); void hina(void); int main() { void (*po[])() = { kitty , sakura , hina }; int i; printf("実行する関数の番号を指定してください 0~2>"); scanf("%d" , &i); if ((i < 0) | (i > 2)) return 0; (*po[i])(); return 0; } void kitty() { printf("Kitty on your lap\n"); } void sakura() { printf("Card Captor SAKURA"); } void hina() { printf("LOVE HINA"); }
クラスの場合
class SuperClass
{
public:
virtual void method_1() = 0;
virtual void method_2() = 0;
};
class classA : public SuperClass
{
public:
virtual void method_1() { cout << "A::method_1" << endl; }
virtual void method_2() { cout << "A::method_2" << endl; }
};
class classB : public SuperClass
{
public:
virtual void method_1() { cout << "B::method_1" << endl; }
virtual void method_2() { cout << "B::method_2" << endl; }
};
利用側では、
auto_ptr<SuperClass> obj;
obj.reset( new classA() );
obj->method_1(); // classA::method_1が呼び出される
obj->method_2();
obj.reset( new classB() );
obj->method_1(); // classB::method_1が呼び出される
obj->method_2();
auto_ptr とは
std::auto_ptr<_Ty> クラス
書式
std::auto_ptr<I> obj(new CR);
使い方は非常に簡単で、コンストラクタにインスタンスを放り込むだけです。
仕組みは非常に分かりやすくて、obj という自動オブジェクトがスコープを抜けて 解体されるときに、デストラクstd::auto_ptr<_Ty>::~auto_ptr がプロパティとして持つ インスタンスを delete してくれる
オペレータ
get() メソッド
_Ty* std::auto_ptr<_Ty>::get(void)const;
というメソッドを経由することで、ポインタ変数を引数として要求する関数にも、 渡すことが出来ます。
reset() メソッド
void std::auto_ptr<_Ty>::reset(_Ty* _Ptr)
というメソッドにインスタンスを渡すと、それまで持っていたインスタンスを安全に 解体しつつ、新しいインスタンスをプロパティとして持ちます。
所有権を持つポインタ変数への代入は本来厳禁ですが、reset() メソッドを経由することで、 そのような操作が安全に行えるわけですね。
release() メソッド
もし、所有権を別の変数に渡さなければならないような状況になった場合は、
_Ty* std::auto_ptr<_Ty>::release(void);
とすることで、この戻り値を代入した先の変数に所有権を渡します。 当然、所有権を渡された変数は、責任を持って解放する必要があります。
コメント 0