C++のstaticに関するまとめ
static(メンバ)変数への代入について知識がうろ覚えだったので、整理した。要点は以下。
- staticな変数は宣言と同時に代入する
- staticなstruct型の初期化は{}で行う.
- class内のstaticなメンバに代入するときはクラスの宣言の外で代入.また型の指定が必要.
- class内struct型がprivateに宣言されていてもクラスの外で初期化できる
- class templateのstaticなメンバ変数、関数への代入はtemplateを指定する
- staticな関数ポインタはtemplate関数で初期化できる
前提知識1
前提知識として関数ポインタの宣言は以下のようにする。
引数名は省略可能。
戻り値 (*変数名)(引数型1 引数名1, 引数型2 引数名2, 続く) void (*hensu_mei)(void* hoge, double* hage);
前提知識2
c++はstruct
型とclass
は(メンバの宣言がデフォルトでpublicかどうかの違いはあるが)基本的に区別がない。
1. staticな変数は宣言と同時に代入する
よくみる構文なので当たり前だが、後述のstaticメンバの初期化とはちょっと異なるのに注意がいる。
/****************************************************************************** * staticな変数は宣言と同時に代入. ******************************************************************************/ void static_test_f0(void*) { } static void (*static_test_fp)(void *) = static_test_f0; //OK //static void (*static_test_fp)(void* hoge); //static_test_fp = static_test_f0; //NG
2. staticなstruct型の初期化は{}で行う.
staticなstruct型の場合。{}
記号の一つの用法。
/****************************************************************************** * staticなstruct型の初期化は{}で行う. ******************************************************************************/ void static_class_test_f(void *) { } struct static_class_test { void (*test)(void *); double hoge; }; static struct static_class_test static_class_test_instance = { static_class_test_f, 1.0 };
3. class内のstaticなメンバに代入するときはクラスの宣言の外で代入. また型の指定が必要.
staticな変数のとの大きな違いは下記。 * staticの宣言と代入を別の場所で行う * 型の指定が必要になる
/****************************************************************************** * class内のstaticなメンバに代入するときはクラスの宣言の外で代入. * また型の指定が必要. ******************************************************************************/ void static_test_f1(void*) { } class static_test1 { public: static_test1() {}; static void (*test)(void *); //static void (*test)(void *) = static_test_f1; //NG //void (*test)(void *) = static_test_f1; //NG static double hoge; //static double hoge = 1.0; //NG }; void (*static_test1::test)(void *) = static_test_f1; //static_test1::test = static_test_f1; //NG double static_test1::hoge = 1.0; //static_test1::hoge = 1.0; //NG
4. class内struct型がprivateに宣言されていてもクラスの外で初期化できる
staticなstruct型のメンバも上記2と3の組み合わせで代入できる。
注意すべき点はstaticなstruct型がprivateなクラス内struct型であっても問題ないという所。
/****************************************************************************** * class内struct型がprivateに宣言されていてもクラスの外で初期化できる ******************************************************************************/ class initialize_struct_test1 { private: struct vtable { void (*draw)(void*); double hoge; }; public: initialize_struct_test1(); static vtable _vTable; }; void test1(void *hoge) { //initialize_struct_test1::vtable hage; //NG } initialize_struct_test1::vtable initialize_struct_test1::_vTable = { test1, 2.0 }; //instaneがないので.は使えない //void (*initialize_struct_test1::_vTable.test)(void*) = test2; //NG //double initialize_struct_test1::_vTable.hoge = 2.0; //NG
5. class templateのstaticの時はtemplateも指定する
class templateにstaticなメンバがあるときはtemplateを指定して代入する。
/****************************************************************************** * class templateのstaticの時はtemplateも指定する ******************************************************************************/ template <typename T> class class_teplate_test { public: class_teplate_test(); static void (*test)(void*); static double hoge; }; void test2(void *hoge) { } template <typename T> void (*class_teplate_test<T>::test)(void *) = test2; template <typename T> double class_teplate_test<T>::hoge = 10.0;
6. staticな関数ポインタはtemplate関数で初期化できる
staticな関数ポインタに限った話ではないが、template関数の用法。
/****************************************************************************** * staticなtemplate関数はtemplateの指定が必要. ******************************************************************************/ template <typename T> void template_func_test_f1(T*) { } void template_func_test_f2(int*) { } static void (*template_func_test)(char*) = template_func_test_f1; //こういうのがやりたいならメタプログラミング //template <typename T> //static void (*template_func_test)(T*) = template_func_test_f2;