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

推荐订阅源

WordPress大学
WordPress大学
T
Threatpost
阮一峰的网络日志
阮一峰的网络日志
美团技术团队
F
Fortinet All Blogs
The GitHub Blog
The GitHub Blog
月光博客
月光博客
V
Visual Studio Blog
T
Tailwind CSS Blog
Stack Overflow Blog
Stack Overflow Blog
博客园 - 聂微东
Jina AI
Jina AI
J
Java Code Geeks
Martin Fowler
Martin Fowler
大猫的无限游戏
大猫的无限游戏
Recorded Future
Recorded Future
C
Check Point Blog
腾讯CDC
N
Netflix TechBlog - Medium
aimingoo的专栏
aimingoo的专栏
罗磊的独立博客
Hacker News: Ask HN
Hacker News: Ask HN
SecWiki News
SecWiki News
博客园 - Franky
Hacker News - Newest:
Hacker News - Newest: "LLM"
N
News | PayPal Newsroom
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
S
Security @ Cisco Blogs
W
WeLiveSecurity
The Last Watchdog
The Last Watchdog
Cloudbric
Cloudbric
F
Full Disclosure
The Cloudflare Blog
Y
Y Combinator Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Google DeepMind News
Google DeepMind News
MongoDB | Blog
MongoDB | Blog
S
Schneier on Security
Schneier on Security
Schneier on Security
Spread Privacy
Spread Privacy
L
LINUX DO - 热门话题
AI
AI
N
News and Events Feed by Topic
T
Tor Project blog
P
Palo Alto Networks Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
H
Hackread – Cybersecurity News, Data Breaches, AI and More
G
Google Developers Blog

博客园 - 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.