C++類成員函數指針

搜到一篇不錯的文章,解釋比較詳細,轉過來。沒有驗證其中代碼的正確性,原文鏈接:http://blog.csdn.net/maojudong/article/details/8194143

測試目錄:

1.普通函數指針指向普通函數
2.普通函數指向非靜態成員函數
3. 類外部的 類函數指針 指向普通函數
4. 類外部的 類函數指針 指向成員函數
5. 類內部的 函數指針 指向成員函數 (類似於第2條)
6. 類內部的 函數指針 指向普通函數


直接上代碼:
  1. #include <iostream>  
  2. #include <string>  
  3. #include <vector>  
  4. #include <map>  
  5. using namespace std;  
  6.    
  7. class Foo  
  8. {  
  9.     public:  
  10.         string m_str;  
  11.         Foo()  
  12.         {  
  13.             m_str = "";  
  14.         }  
  15.           
  16.         static void testFunc2(int a)  
  17.         {  
  18.             cout<<"Foo:void testFunc2(int a)"<<endl;  
  19.             cout<<a<<endl;  
  20.         }  
  21.           
  22.         void testFunc4(int a)  
  23.         {  
  24.             cout<<"Foo:void testFunc4(int a)"<<endl;  
  25.             cout<<a<<endl;  
  26.         }  
  27.         static void testFunc5(int a)  
  28.         {  
  29.             cout<<"Foo:void testFunc5(int a)"<<endl;  
  30.             cout<<a<<endl;  
  31.         }  
  32.           
  33.         void (*pTestFunc5)(int a);  
  34.         void (*pTestFunc6)(int a);  
  35. };  
  36.   
  37. void (*pTestFunc1)(int a);  
  38. void (*pTestFunc2)(int a);  
  39. void (Foo::*pTestFunc3)(int a);  
  40. void (Foo::*pTestFunc4)(int a);  
  41.   
  42. void testFunc1(int a)  
  43. {  
  44.     cout<<"func1 pointer test"<<endl;  
  45.     cout<<a<<endl;  
  46. }  
  47.   
  48. void testFunc3(int a)  
  49. {  
  50.     cout<<"func3 pointer test"<<endl;  
  51.     cout<<a<<endl;  
  52. }  
  53.   
  54. void testFunc6(int a)  
  55. {  
  56.     cout<<"func6 pointer test"<<endl;  
  57.     cout<<a<<endl;  
  58. }  
  59.   
  60.   
  61. int main(int argc, const char *argv[])  
  62. {  
  63.   
  64.     Foo foo;  
  65.     //foo.test("woo",100);  
  66.       
  67.     pTestFunc1 = testFunc1;     //經常用這個方法  
  68.     (*pTestFunc1)(1);  
  69.       
  70.      pTestFunc2=&foo.testFunc2;  
  71.     (*pTestFunc2)(2);  
  72.       
  73.     //pTestFunc3 = &testFunc3;  //編譯器報錯,不可以這麼使用  
  74.       
  75.     pTestFunc4 = &Foo::testFunc4; //初始化的時候必須帶有&Foo::  
  76.   
  77.     //pTestFunc4(4);//編譯器報錯,不可以這麼使用  
  78.     //foo.pTestFunc4(4);//編譯器報錯,不可以這麼使用  
  79.     //foo.*pTestFunc4(4);//編譯器報錯,不可以這麼使用  
  80.     //foo.(*pTestFunc4)(4);//編譯器報錯,不可以這麼使用  
  81.     (foo.*pTestFunc4)(4);   //正常運行  
  82.       
  83.     foo.pTestFunc5=&Foo::testFunc5;  
  84.     foo.pTestFunc5(5);  
  85.       
  86.     foo.pTestFunc6=&testFunc6;  
  87.     foo.pTestFunc6(6);  
  88.       
  89.     return 0;  
  90. }  

程序分析:
1.普通函數指針指向普通函數
pTestFunc = &testFunc;
或者
pTestFunc = testFunc;
調用方式
pTestFunc(1)
(pTestFunc)(1)
(*pTestFunc)(1)

2.普通函數指向非靜態成員函數
pTestFunc=foo.testFunc2;  編譯器報錯,提示不匹配
error: argument of type ‘void (Foo::)(int)’ does not match ‘void (*)(int)’

pTestFunc=&foo.testFunc2;  編譯器報錯,提示不匹配
error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function.  Say ‘&Foo::testFunc’
error: cannot convert ‘void (Foo::*)(int)’ to ‘void (*)(int)’ in assignment

pTestFunc=Foo::testFunc2;  編譯器報錯
error: invalid use of non-static member function ‘void Foo::testFunc(int)’

pTestFunc=&Foo::testFunc2; 編譯器報錯
error: cannot convert ‘void (Foo::*)(int)’ to ‘void (*)(int)’ in assignment

普通函數指向靜態成員函數
將代碼更改一下後,將成員函數前加入一個static關鍵字
則下面的初始化方式編譯和運行正常
pTestFunc2=Foo::testFunc2;
pTestFunc2=&Foo::testFunc2;
pTestFunc2=foo.testFunc2;
pTestFunc2=&foo.testFunc2;

調用方式和普通函數指向普通函數一致
pTestFunc2(2)
(pTestFunc)2(2)
(*pTestFunc)2(2)

3. 類外部的 類函數指針 指向普通函數
這種用法就是錯誤的,所以編譯器不通過
pTestFunc3 = testFunc3;  編譯器報錯,
test5.cpp:83: error: cannot convert ‘void(int)’ to ‘void (Foo::*)(int)’ in assignmen
pTestFunc3 = &testFunc3;
test5.cpp:83: error: cannot convert ‘void (*)(int)’ to ‘void (Foo::*)(int)’ in assignmen

4. 類外部的 類函數指針 指向成員函數
初始化指針的方式
pTestFunc4 = &Foo::testFunc4; //初始化的時候必須帶有&Foo::
pTestFunc4 = Foo::testFunc4; //編譯器報錯
pTestFunc4 = foo.testFunc4; //編譯器報錯
pTestFunc4 = &foo.testFunc4; //編譯器報錯

調用方式:
pTestFunc4(4);//編譯器報錯,不可以這麼使用
foo.pTestFunc4(4);//編譯器報錯,不可以這麼使用
foo.*pTestFunc4(4);//編譯器報錯,不可以這麼使用
foo.(*pTestFunc4)(4);//編譯器報錯,不可以這麼使用
(foo.*pTestFunc4)(4)//正常運行,所以必須要帶有括號
如果foo爲指針
Foo *foo=new Foo();
(foo->*pTestFunc4)(4)


5. 類內部的 函數指針 指向成員函數 (類似於第2條)
foo.pTestFunc5=foo.testFunc5;  編譯器報錯
test5.cpp:125: error: argument of type ‘void (Foo::)(int)’ does not match ‘void (*)(int)’

foo.pTestFunc5=&foo.testFunc5; 編譯器報錯
test5.cpp:123: error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function.  Say ‘&Foo::testFunc’
test5.cpp:123: error: cannot convert ‘void (Foo::*)(int)’ to ‘void (*)(int)’ in assignment

foo.pTestFunc5=Foo::testFunc5;編譯器報錯
foo.pTestFunc5=&Foo::testFunc5;  編譯器報錯

聲明爲靜態函數後(與第2條相似),編譯和運行都OK
foo.pTestFunc5=foo.testFunc5;
foo.pTestFunc5=&foo.testFunc5;
foo.pTestFunc5=Foo::testFunc5;
foo.pTestFunc6=&Foo::testFunc5;

6. 類內部的 函數指針 指向普通函數
編譯和運行都OK
foo.pTestFunc2=testFunc6;
foo.pTestFunc2=&testFunc6;


測試代碼的下載位置:

注:

如果是在類成員函數內部使用函數指針,可以採用如下方法:

(this->*pTestFunction4)(4);


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章