搜到一篇不錯的文章,解釋比較詳細,轉過來。沒有驗證其中代碼的正確性,原文鏈接:http://blog.csdn.net/maojudong/article/details/8194143
測試目錄:
1.普通函數指針指向普通函數 2.普通函數指向非靜態成員函數 3. 類外部的 類函數指針 指向普通函數 4. 類外部的 類函數指針 指向成員函數 5. 類內部的 函數指針 指向成員函數 (類似於第2條) 6. 類內部的 函數指針 指向普通函數
直接上代碼:
-
#include <iostream>
-
#include <string>
-
#include <vector>
-
#include <map>
-
using namespace std;
-
-
class Foo
-
{
-
public:
-
string m_str;
-
Foo()
-
{
-
m_str = "";
-
}
-
-
static void testFunc2(int a)
-
{
-
cout<<"Foo:void testFunc2(int a)"<<endl;
-
cout<<a<<endl;
-
}
-
-
void testFunc4(int a)
-
{
-
cout<<"Foo:void testFunc4(int a)"<<endl;
-
cout<<a<<endl;
-
}
-
static void testFunc5(int a)
-
{
-
cout<<"Foo:void testFunc5(int a)"<<endl;
-
cout<<a<<endl;
-
}
-
-
void (*pTestFunc5)(int a);
-
void (*pTestFunc6)(int a);
-
};
-
-
void (*pTestFunc1)(int a);
-
void (*pTestFunc2)(int a);
-
void (Foo::*pTestFunc3)(int a);
-
void (Foo::*pTestFunc4)(int a);
-
-
void testFunc1(int a)
-
{
-
cout<<"func1 pointer test"<<endl;
-
cout<<a<<endl;
-
}
-
-
void testFunc3(int a)
-
{
-
cout<<"func3 pointer test"<<endl;
-
cout<<a<<endl;
-
}
-
-
void testFunc6(int a)
-
{
-
cout<<"func6 pointer test"<<endl;
-
cout<<a<<endl;
-
}
-
-
-
int main(int argc, const char *argv[])
-
{
-
-
Foo foo;
-
-
-
pTestFunc1 = testFunc1;
-
(*pTestFunc1)(1);
-
-
pTestFunc2=&foo.testFunc2;
-
(*pTestFunc2)(2);
-
-
-
-
pTestFunc4 = &Foo::testFunc4;
-
-
-
-
-
-
(foo.*pTestFunc4)(4);
-
-
foo.pTestFunc5=&Foo::testFunc5;
-
foo.pTestFunc5(5);
-
-
foo.pTestFunc6=&testFunc6;
-
foo.pTestFunc6(6);
-
-
return 0;
-
}
程序分析:
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);