C++使用函数指针如何实现 C#里委托的效果

2025-03-03 07:57:21
推荐回答(2个)
回答1:

C++可以把不同类的函数放在一个数组

假如你有两个类, widget和gadget, 他们有个同名函数 void put( int )

你可以通过继承+模板的方式, 把他们加入数组vector中.

class base//建立一个基类, 来避开静态类型检查, 
{
public: 
 virtual void put( int )// 相同签名的函数 
 {} 
 virtual ~base()= 0{}  ;
} ;
 
class policy
{
public:
 vector vec ;// 多态数组 
 ~policy()
 {
  for( size_t i = 0 ; i < vec.size() ; ++i )
   delete vec[i] ;
 }
public:
 template
 void AddThis( T* v )
 {
  class Dev : public base // 利用本地类 + 模板, 把不同类型对象加入数组 
  {
  private:
   T* m_p ;
  public:
   Dev( T* p ) : m_p( p ) { }
  public:
   void put( int i )
   {
    return m_p->put( i ) ;
   }
  } ;
  Dev* p = new Dev( v ) ;
  vec.push_back( p ) ;
 }
public:
 void operator()( int ii)
 {
  for( size_t i = 0 ; i < vec.size() ; ++i )
   vec[i]->put( ii ) ; 
 }
} ;
 
class widget
{
public:
 void put( int i ) 
 {
  cout << "widget put " << i << endl ;
 }
 virtual ~widget(){}
} ;
 
class gadget
{
public:
 void put( int i ) 
 {
  cout << "gadget put " << i << endl ;
 }
 virtual ~gadget() { }
} ;

 
int main()
{
 widget w ;
 gadget g ;
 policy po ;
 po.AddThis( &w ) ;// 加入widget对象 
 po.AddThis( &g ) ;// 加入gadget对象 
 po( 10 ) ; // 对w和g调用相同函数 
}

 

利用函数指针, 是可以调用不同名字, 相同签名的函数,但这没太大意思, 我们最需要的是这种用法

policy< void (T::*)( int, int ) > p1 ; // 接受void func( int, int )

policy< int ( T::* )( double, int ) > p2 ; // 接受int func( double , int )

但这用C++来实现几乎不可能, STL也只是通过unary_function和binary_function最多支持两个形参的函数.

因为C++是静态类型检查的语言, 要编写类型安全的多态静态数组,几乎是不可能的

所以你必须为每次使用不同的"同名函数"都要修改下源代码,这样很笨拙.

回答2:

C#中采用委托的方式,其实和C++的typedef非常相像,都是必须先定义一个类型,然后用该类型去声明一个变量。最大的不同在赋值阶段,C++只需要简单的将函数地址赋给指针,而C#必须用new声明一个对象,并且还要求相应的函数作为形参传入。在这个阶段,似乎C#显得更为复杂。到了调用阶段,C++和C#都可以容器后加个括号就能完成调用,但C++还多了一种*的方式。