惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
SegmentFault 最新的问题
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Attack and Defense Labs
Attack and Defense Labs
F
Full Disclosure
Vercel News
Vercel News
N
News | PayPal Newsroom
The GitHub Blog
The GitHub Blog
H
Hacker News: Front Page
H
Heimdal Security Blog
P
Privacy International News Feed
博客园 - 司徒正美
Google DeepMind News
Google DeepMind News
N
Netflix TechBlog - Medium
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cisco Blogs
L
Lohrmann on Cybersecurity
D
Docker
Recent Announcements
Recent Announcements
Security Archives - TechRepublic
Security Archives - TechRepublic
人人都是产品经理
人人都是产品经理
C
CXSECURITY Database RSS Feed - CXSecurity.com
P
Proofpoint News Feed
T
Tailwind CSS Blog
C
Check Point Blog
博客园 - 叶小钗
Google Online Security Blog
Google Online Security Blog
Martin Fowler
Martin Fowler
Stack Overflow Blog
Stack Overflow Blog
博客园 - 聂微东
S
Secure Thoughts
博客园 - Franky
博客园_首页
阮一峰的网络日志
阮一峰的网络日志
P
Palo Alto Networks Blog
Latest news
Latest news
量子位
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 三生石上(FineUI控件)
The Cloudflare Blog
Last Week in AI
Last Week in AI
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Cyberwarzone
Cyberwarzone
小众软件
小众软件
Cisco Talos Blog
Cisco Talos Blog
Hacker News: Ask HN
Hacker News: Ask HN
T
Threatpost
T
Tenable Blog
P
Privacy & Cybersecurity Law Blog
WordPress大学
WordPress大学

博客园 - dannyr|一个都不能少!

DipperRiver.Net通信协议设计 计划开发memcache 的.net版本,命名DipperRiver.Net Net1.1添加目录共享,并设置访问权限 Access数据库的文本、备注数据类型的COLUMN_FLAGS说明 生命诚可贵 如何关闭子线程?征集析构函数与多线程的讨论! Dev GridControl的Outlook风格定制 WinForm MDI动态加载form DevExpress's tip 检测浏览器类型的js Spry1.4 下载 Spry PreRelease 1.4 发布 Spry Framework入门(五)——数据集过滤及淡入淡出效果 Flex2.0文件上传功能(Flex2.0正式版) 关于JSON Spry Framework入门(四)——XML数据集排序 Spry Framework入门(三)——框架结构 Spry Framework入门(二)——XML数据集及主从表显示 Spry Framework入门(一)——XML数据集及显示
function object(functor) ...
dannyr|一个都不能少! · 2007-09-15 · via 博客园 - dannyr|一个都不能少!

As is known,in many advanced programming languages(esp. object oriented ones) like c/c++,c#,Java,etc., the function is only one of the programming syntax constructs,unlike that in some pure interpreted programming lanuage such as Javascript,SmallTalk and so on,which are also object oriented,the function itself is a first-class object,however,for example:

function Foo() { // note: Foo is an object
    this.sampleMemVar = 123;
    
this.sampleMemFun = function() {}; // create a new function object
    function() {}; // anonymouse function object
    var f = function(){}; // equal to function f() {} declaration,also create new function object
};


 

As a result,foo can behaves in the same way as regular object do,that is to say,foo can have properties,member functions,and can be extended,see below:


Foo.prototype.sampleVar 
= 0;
Foo.prototype.sampleFun 
= function(arglist) {}; // prototype is one of the properties of object Foo
Foo.sampleStaticVar = "sample static variable"// static variable
Foo.sampleStaticFun = function() // extend Foo with a static function
var foo = new Foo(); // applying new operator on a function object causing an instance of an Object is created with the members declared in the constructor,i.e.,Foo.
foo.toString(); // inherited from Object
typeof(foo); // you can call typeof operator on foo,where Object is returned
typeof(Foo); // call tpyeof operator on Foo,where Function is returned
printf(Foo.sampleStaticVar);
foo.sampleMemVar 
= 100// access instance variable
Foo.sampleStaticFun(); // call static method
foo.sampleMemFun(); // call instance method


 

No need to enumerate the examples any more. You can see that the function has no much differences from general objects,except that it does inherites from Function on the other hand.
 
Then how about the situation in c/c++,or others?
For example, we have a function,which can perform some action on two operands,and the specified action can only be determined at runtime.Then how to solve this problem?
 
Of course,you can use (memebr) function pointer like:

typedef int (*OpFunc)(int left,int right);

 
but you should first know the argument types and return type.
how about template?

template<class _Arg1,class _Arg2,class _Result>
_Result(
*OpFunc)(_Arg1 arg1,_Arg2 arg2); // this does not compile


 

You could never use template directly on typedef or object declarations.
Then maybe you want to encapsulate the concept in this way:

template<class _Arg1,class _Arg2,class _Result>
class Performer
{
public:
 typedef _Result (
*OpFunc)(_Arg1,_Arg2);
 Performer(OpFunc _opfunc) : m_opfunc(_opfunc)
 {
  _ASSERT(NULL 
!= _opfunc);
 }
 _Result Perform(_Arg1 arg1,_Arg2 arg2)
 {
  
return m_opfunc(arg1,arg2);
 }
private:
 OpFunc m_opfunc;
};


 

Yes,this works. However,function pointer itself is not an object oriented construct,as a result,lack of flexibility and extensibility.
 
Then,if you're familar with c#,you may want to use delegate.
And unlike template in c++,you can apply generic on delegate directly.


delegate _Result OpFunc<_Arg1,_Arg2,_Result>(_Arg1 arg1,_Arg2 arg2);
class Performer<_Arg1, _Arg2, _Result>
{
    
private OpFunc<_Arg1, _Arg2, _Result> opfun = null;
    
public Performer(OpFunc<_Arg1, _Arg2, _Result> _opfun)
    {
        
if (null == _opfun) throw new ArgumentException();
        
this.opfun = _opfun;
    }
    
public _Result Perform(_Arg1 arg1, _Arg2 arg2)
    {
        
return opfun(arg1, arg2);
    }
}


 

you can even implement you delegate in c++,only by making a wrapper to any function pointer.
No matter what you do with delegate,you are actually using function pointers,then again,lack of flexibility and extensibility.
 
So, why not use polymorphism?
If we can store the runtime action performer in an object,e.g.,action_performer,and we call the method on this object,where different object has different implementation for that action.


template
<class _Arg1,class _Arg2,class _Result>
class PerformerBase
{
public:
 
virtual _Result Perform(_Arg1 arg1,_Arg2 arg2) = 0;
};
template
<class _Arg1,class _Arg2,class _Result>
class AddPerformer : public PerformerBase<_Arg1,_Arg2,_Result>
{
public:
 _Result Perform(_Arg1 arg1,_Arg2 arg2)
 {
  
return arg1 + arg2;
 }
};
template
<class _Arg1,class _Arg2,class _Result>
class MinusPerformer : public PerformerBase<_Arg1,_Arg2,_Result>
{
public:
 _Result Perform(_Arg1 arg1,_Arg2 arg2)
 {
  
return arg1 - arg2;
 }
};


 

Yes,this also works and we can gain much flexibility and extensibility from this solution.
Then if we we can use function object as we do in Javascript,we can gain much more.
Forget operator overloading?( return to your c++ textbook for a look:-))
we can obtain a function object by encapsulate the function and overload it call operator,i.e.().
For example,

class Functor
{
public:
    
int operator()(int a,int b) { return a + b; }
};
Functor myFuncObj;
int x = myFuncObj(1,2);


 

Quite easy,right?
 
OK,then let's return to our problem,which is now trivial,given below:

template<class _Arg1,class _Arg2,class _Result>
class FunctorBase
{
public:
 
virtual _Result operator()(_Arg1 arg1,_Arg2 arg2) = 0;
};
template
<class _Arg1,class _Arg2,class _Result>
class AddFunctor : public FunctorBase<_Arg1,_Arg2,_Result>
{
public:
 _Result 
operator()(_Arg1 arg1,_Arg2 arg2)
 {
  
return arg1 + arg2;
 }
};
template
<class _Arg1,class _Arg2,class _Result>
class MinusFunctor : public FunctorBase<_Arg1,_Arg2,_Result>
{
public:
 _Result 
operator()(_Arg1 arg1,_Arg2 arg2)
 {
  
return arg1 - arg2;
 }
};
template
<class _Arg1,class _Arg2,class _Result>
class Performer
{
public:
 Performer(FunctorBase
<_Arg1,_Arg2,_Result> & functor)
  : m_functor(functor)
 {
 }
 _Result Perform(_Arg1 arg1,_Arg2 arg2)
 {
  
return m_functor(arg1,arg2);
 }
private:
 FunctorBase
<_Arg1,_Arg2,_Result> & m_functor;
};


 

In conclusion, you can implement your own specific function object(functor) even in c++,c#,etc.,then you can use function as general objects in your program with high flexibility,resuability and extensibility. Actually, if you look into the STL,you will find that many functions receive a functor as a parameter,e.g.,find_if in <algorithm> receives a predictor as a searching criteria. see declaration below:

template<class InputIterator, class Predicate>
   InputIterator find_if(
      InputIterator _First,
      InputIterator _Last,
      Predicate _Pred
   );


 

then you can call like this:

int arr[] = {1,2,3,4,5};
int * found = find_if(arr,arr + _countof(arr),greater<int>(2)); // find element that is greater thatn 2.
 

functors are declared in <functional> in STL.