明確一點即回調函數須要是靜態函數。緣由:編程
若不想使用C式函數做爲回調函數呢?(破壞封裝性)函數
下面講解一下第二點,我認爲比較好用。this
class A { public: static void staticmember(){cout<<"static"<<endl;} //static member void nonstatic(){cout<<"nonstatic"<<endl;} //nonstatic member virtual void virtualmember(){cout<<"virtual"<<endl;};//virtual member }; int main() { A a; //static成員函數,取得的是該函數在內存中的實際地址,並且由於static成員是全局的,因此不能用A::限定符 void (*ptrstatic)() = &A::staticmember; //nonstatic成員函數 取得的是該函數在內存中的實際地址 void (A::*ptrnonstatic)() = &A::nonstatic; //虛函數取得的是虛函數表中的偏移值,這樣能夠保證能過指針調用時一樣的多態效果 void (A::*ptrvirtual)() = &A::virtualmember; //函數指針的使用方式 ptrstatic(); (a.*ptrnonstatic)(); (a.*ptrvirtual)(); }
直接用類名引出非靜態成員函數,賦值給函數指針:.net
//nonstatic成員函數 取得的是該函數在內存中的實際地址 void (A::*ptrnonstatic)() = &A::nonstatic;
隨後須要運行回調函數的時候,使用一個輔助變量來運行,格式爲:(變量名. * 函數指針)(參數)。指針
(a.*ptrnonstatic)();
若是在咱們的編程過程當中:code
咱們可使用:blog
bool (DoTask::*function)(void *arg);
其中DoTask是一個類名,上面寫的就是一個返回值爲bool類型,參數爲void *類型的函數指針,指向DoTask這個類中的成員函數。內存
而後調用的時候咱們能夠:作用域
Dotask d; //注意ReadData函數不用加括號,要加做用域和地址符 bool (DoTask::*function)(void *arg) = &DoTask::ReadData; (d.*function)(NULL);
注意點就是賦值給函數指針的時候須要取地址符、加做用域、函數不加括號,直接函數名便可。get
調用的時候,用一個實例去調用函數指針便可。
假如咱們將函數指針放在一個結構體中:
struct task { bool (DoTask::*function)(void *arg); void *arg; };
那麼咱們調用它的時候也是同樣的。
struct task t; t.function = &DoTask::ReadData; ... DoTask d; (d.*(t.function))(NULL); //完成調用。
如今看調用這一步。參照上面的:
(d.*function)(NULL)
只不過function如今存在結構體中,替換成從結構體中取出來便可:
function 替換成 t.function
代入便可。