在學習C++的時候對這個函數對象還沒什麼感受,可是在此次學習Boost.Thread的時候才發現,函數對象的重要性以及方便性。在傳統的C線程中,會有一個void*參數用於給線程函數傳遞參數,可是Boost.Thread去是直接構造線程對象,除了一個函數名以外沒有其它的參數,那麼若是使用傳統的方式(直接將函數名稱傳入)就只能執行無參數的函數了,因此這裏使用了函數對象來實現參數的傳遞。ios
(一)函數對象算法
在來回顧一下什麼是函數對象,就是一個重載'()'運算符的類的對象。這樣就能夠直接使用‘對象名()’的方式,這跟調用函數同樣,因此稱謂函數對象。看個例子:函數
1 #include <iostream> 2 #include <string> 3 4 class Printer{ 5 public: 6 explicit Printer(){}; 7 void operator()(const std::string & str)const{ 8 std::cout<<str<<std::endl; 9 } 10 }; 11 12 int main(int atgc,char * argv[]){ 13 Printer print; 14 print("hello world!"); 15 return 0; 16 }
如今來講說函數對象有哪些好處:學習
(1)函數對象有本身的狀態,即它能夠攜帶本身的成員函數,並且這個函數對象在屢次調用的過程當中它的那些狀態是共享的,而函數則不能作到這點(除非定義函數內部的靜態變量或者全局變量)。this
(2)函數對象有本身的類型,而普通函數則沒有。在使用STL的容器時能夠將函數對象的類型傳遞給容器做爲參數來實例化相應的模板,從而來定製本身的算法,如排序算法。spa
假設我須要一個數字產生器,我給定一個初始的數字,而後每次調用它都會給出下一個數字。線程
#include <iostream> #include <string> #include <vector> #include <algorithm> class SuccessiveNumGen { public: SuccessiveNumGen(int origin = 0):m_origin(origin){} int operator()(){ return m_origin++; } private: int m_origin; }; int main(int argc,char * argv[]){ std::vector<int> dest; generate_n(back_inserter(dest),10,SuccessiveNumGen(3)); for(int i=0;i<10;i++){ std::cout<<dest[i]<<std::endl; } return 0; }
注:此處用到了STL的算法,generate_n會調用SuccessiveNumGen函數十次,back_inserter會將SuccessiveNumGen函數的返回值插入到dest中。3d
(二)Boost.Thread中函數對象的使用code
#include <boost/thread/thread.hpp> #include <iostream> #include <string> void wait(int sec){ boost::this_thread::sleep(boost::posix_time::seconds(sec)); } boost::mutex mutex; class SayHello{ public: explicit SayHello(const std::string & name,int times) :_name(name),_times(times){} void operator()()const{ for(int i=0;i<_times;i++){ wait(1); boost::lock_guard<boost::mutex> lock(mutex); std::cout<<_name<<" says hello ("<<i+1<<")"<<std::endl; } } private: std::string _name; int _times; }; int main(int argc,char * argv[]){ SayHello lux("Lux",5); SayHello jax("Jax",5); boost::thread thr1(lux); boost::thread thr2(jax); thr1.join(); thr2.join(); return 0; }