函数指针的用法
函數指標一些相關的用法和注意事項。以下將詳細說明:
1. 基本寫法:
這是最常見且明確的寫法,尤其在處理重載函數時非常有用。
void (GirlFriend::*girl2)(QString) = &GirlFriend::hungry;
void
: 指標所指向的函數的回傳型別。(GirlFriend::*)
: 表示這是一個指向GirlFriend
類別成員函數的指標。girl2
: 指標變數的名稱。(QString)
: 指標所指向的函數的參數列表。&GirlFriend::hungry
: 要指向的函數的位址。
2. 使用 typedef
或 using
進行簡化:
當需要多次使用同一種函數指標型別時,可以使用 typedef
(C風格) 或 using
(C++11引入) 來定義別名,使程式碼更簡潔易懂。
// 使用 typedef
typedef void (GirlFriend::*GirlFriendHungryFunc)(QString);
GirlFriendHungryFunc girl2 = &GirlFriend::hungry;
// 使用 using (更推薦)
using GirlFriendHungryFunc = void (GirlFriend::*)(QString);
GirlFriendHungryFunc girl2 = &GirlFriend::hungry;
3. 使用 auto
(C++11引入):
在某些情況下,如果編譯器可以推斷出函數指標的型別,可以使用 auto
關鍵字來簡化宣告。但對於類別成員函數指標,通常還是建議明確寫出型別,以增加程式碼的可讀性。
auto girl2 = &GirlFriend::hungry; // 注意:此處 girl2 的型別仍然是 void (GirlFriend::*)(QString)
4. 指向靜態成員函數的指標:
指向靜態成員函數的指標與指向一般函數的指標類似,不需要指定類別名稱。
class MyClass {
public:
static void myStaticFunction(int x);
};
void (*staticFuncPtr)(int) = &MyClass::myStaticFunction; // 注意:沒有 MyClass::*
5. 作為函數參數的函數指標:
函數指標可以作為函數的參數,允許將不同的函數傳遞給同一個函數。這在實現回調函數或策略模式時非常有用。
void executeFunction(void (*funcPtr)(int), int value) {
funcPtr(value);
}
void myFunction(int x) {
// ...
}
executeFunction(myFunction, 10);
6. 注意事項:
-
成員函數指標需要物件: 成員函數指標需要一個物件實例才能呼叫。例如:
GirlFriend gf; (gf.*girl2)("我想吃冰淇淋"); // 使用物件呼叫 GirlFriend *gfPtr = new GirlFriend; (gfPtr->*girl2)("我想吃蛋糕"); // 使用指標呼叫
-
this
指標: 在類別成員函數中,可以使用this
指標來呼叫其他成員函數,包括使用函數指標呼叫。 -
const 成員函數: 如果要指向
const
成員函數,函數指標的宣告也需要加上const
。class MyClass { public: void myConstFunction() const; }; void (MyClass::*constFuncPtr)() const = &MyClass::myConstFunction;
-
虛擬函數: 函數指標也可以指向虛擬函數,但這會涉及到虛擬函數表 (vtable) 的查找,其行為與直接呼叫虛擬函數相同。
總結:
雖然新的 Qt 連接語法 (connect(sender, &Sender::signal, receiver, &Receiver::slot);
) 大部分情況下都取代了手動使用函數指標的需求,但在處理重載訊號/槽,或是需要更底層的控制時,函數指標仍然非常有用。理解函數指標的不同寫法和用法,能讓你更靈活地運用 C++ 和 Qt。