C++不像其他很多編程語言有接口、委托或者協議的概念,但是利用純虛函數和C++多重繼承的特性,我們也能實現接口、委托或協議要做的事情,下面的通過一個人設置鬧鐘然後被鬧鐘喚醒的例子來說明如何在C++中實現委托回調。
#include
#include
using std::cout;
using std::endl;
// 前向引用聲明
class Person;
// 用純虛函數設計一個協議
// 實現該協議的類有一個被喚醒的行為
class Awakable {
public:
// 純虛函數
virtual void beAwaken() = 0;
};
// 鬧鐘類
class AlarmClock {
public:
// 委托方(誰委托了鬧鐘提供喚醒服務)
Awakable *delegate;
// 在指定時間後報警
void alarmAfter(int) const;
};
void AlarmClock::alarmAfter(int seconds) const {
sleep(seconds);
cout << 叮咚 叮咚 叮咚 << endl;
// 回調委托方的方法
delegate->beAwaken();
}
// 人類(實現了Awakable協議可以被喚醒)
class Person : public Awakable {
public:
// 啟動鬧鐘並指定喚醒時間
void rollClock(int);
// 協議中的被喚醒的行為
void beAwaken();
};
void Person::rollClock(int seconds) {
cout << 人設置了鬧鐘 << seconds << 秒後響鈴 << endl;
// 在棧上創建鬧鐘對象
AlarmClock ac;
// 設置委托方
ac.delegate = this;
ac.alarmAfter(seconds);
}
void Person::beAwaken() {
cout << 人被鬧鐘喚醒了 << endl;
}
int main(void) {
// 在堆上創建人的對象
Person *person = new Person;
// 人啟動鬧鐘設置5秒後被喚醒
person->rollClock(5);
// 釋放指針指向的堆空間
delete person;
return 0;
}
程序寫到這裡,我相信已經不用更多的言語來解釋如何實現協議委托了。其實各種編程語言的表象千變萬化但是實質幾乎沒有區別。類似的功能在Java中用接口(interface)可以做到,在C#中可以使用委托(delegate),在Objective-C中可以使用協議(protocol),Swift中也有協議這個概念。但是如果你能夠理解函數式編程的理念,還有更簡單有效的方式就是使用Lambda函數,將一個回調函數直接作為參數傳入一個函數或方法中,而Java(Java 8)和C#中都提供了Lambda表達式,OC中也有block來實現相同的功能。那麼C++呢,別忘了C++中還有仿函數(函數對象)的概念,這些不都是一致的嗎?當然,支持函數式編程范式的語言就更不用說了,就像JavaScript中可以把函數傳入函數中,Swift不也是如此嗎?