C++之TR1::function

Tr1::function的介紹

它是一個類模板,類的成員變量是一個函數指針。可以把它看作一個智能函數指針(和shared_ptr智能指針對比着理解)。

 

一. 頭文件

#include<functional>

 

二. 使用

//t.cpp
#include "stdafx.h"
#include<iostream>
#include<functional>
using namespace std;
void foo(int i){cout<<"aaa"<<endl;}
void (*p)(int)=foo;
int _tmain(int argc, _TCHAR* argv[])
{
       function<void (int)> fm;
       fm=foo;
       (*p)(2);
       fm(2);
       return 0;
}

可以看出它和函數指針很像,但是它具有很多函數指針做不到的事情。下面慢慢說。

 

1. 定義一個function對象。

由於function是一個類模板,所以使用起來,首先定義一個類的對象。

Function <void (int)> fm;-----<>中第一個參數是要綁定函數的返回類型,第二個參數是要綁定的函數的參數列表。注意使用小括號括起來。

 

2. 像函數指針一樣,這個指針需要指向某個函數。

fm=function<void (int)>(foo);

 

3. 由於類模板function重載了()符號。所以使用起來比函數指針更易用。

Fm(2);

 

下面說一下爲什麼要有tr1::function.也就是它相對於函數指針的優點:

1. 綁定的函數的類型

函數指針只能綁定普通的外部函數。而tr1::function可以綁定各種函數類型。

(1) 外部普通函數和類的static函數

//t.cpp
#include "stdafx.h"
#include<iostream>
#include<functional>
using namespace std;
class A{
public:
static void foo(inti){cout<<"aaa"<<endl;}
};
int _tmain(int argc, _TCHAR* argv[])
{
       function<void (int)>fm(A::foo);
       //function<void (int)> fm;fm=function<void(int)>(A::foo); also OK
       void (*p)(inti)=A::foo();//error
       fm(2);
       return 0;
}

因爲外部函數和類的static很相似,所以使用起來也很相似。

 

(2)類的非static成員函數。

//t.cpp
#include "stdafx.h"
#include<iostream>
#include<functional>
using namespace std;
class A{
public:
void foo(int i){cout<<"aaa"<<endl;}
};
int _tmain(int argc, _TCHAR* argv[])
{
       A b;
       function<void (int)>fm=bind(&A::foo,b,tr1::placeholders::_1);//OK
       //function<void (int)> fm=b.foo();//error
       fm(2);
       return 0;
}

注意必須是&A::foo(),這個符號&不能少,這是由function決定的。這裏bind中的foo只是接受一個參數,而實際上是需要兩個參數,因爲static函數是沒有對象就存在的,而非static成員函數必須有對象之後才能存在,所以這個成員函數需要指明是哪個對象的成員函數。

 

(3) 綁定虛函數,呈現多態

//t.cpp
#include "stdafx.h"
#include<iostream>
#include<functional>
using namespace std;
class A{
public:
  virtual void foo(int i){cout<<"A"<<endl;}
  void fun(){
       function<void (int)>fm=bind(&A::foo,this,tr1::placeholders::_1);
       fm(2);//這裏和直接調用foo();效果是一樣的。並沒有改變它的多態性質
}
};
class B:public A
{
public:void foo(inti){cout<<"B"<<endl;}
};
int _tmain(int argc, _TCHAR* argv[])
{
       B b;
       b.fun();
       return 0;
}

 其實這裏並不是function的什麼特殊性質,而只是function是一個普通的類而已,不是因爲它而改變多態性質。這裏和直接調用foo();的效果一樣。

 

2. 構造函數中的參數

(1) 首先是函數名,這個上面已經講過

 

(2) 可以是一個函數對象!(函數對象就是一個重載了操作符”()”的類,這樣類的對象可以:a(…);使用起來很像函數,所以叫做函數對象)

//t.cpp
#include "stdafx.h"
#include<iostream>
#include<functional>
using namespace std;
class A{
public:
       void operator()(int i){cout<<"A"<<endl;
       }
       void foo(){}
};
int _tmain(int argc, _TCHAR* argv[])
{
       A a;
       function<void (int)> fm(a);
       fm(2);
       return 0;
}

注意這裏,居然可以把一個類對象放到function裏!這好像違反了function函數指針的原意。但是注意:由於function沒有提供返回它擁有的東西的函數,所以這裏只能fm(2);來調用類中的重載()函數。不能調用類中的其他函數。所以它還是一個函數指針,只是這個指針指向的函數是一個類中的重載()函數罷了。

 

3. function類模板的其他幾個member函數

(1) assign函數,爲這個函數指針分配一個函數實體。

(2) swap函數,交換兩個函數指針擁有的東西

(3) target函數,測試本函數指針指向的函數類型是不是爲指定類型

(4) target_type函數,獲取函數指針指向的函數的類型信息

不常用,也不好用,所以瞭解即可。

 

總結:其實function和函數指針很像,只是比函數指針能多指向一些特別的函數而已。

普通函數指針只能指向普通的外部函數

Function可以指向:外部函數,類的static函數,類的非static函數,類的virtual函數,類的對象(函數對象)。

 

發佈了45 篇原創文章 · 獲贊 32 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章