C++可以把不同类的函数放在一个数组
假如你有两个类, widget和gadget, 他们有个同名函数 void put( int )
你可以通过继承+模板的方式, 把他们加入数组vector中.
class base//建立一个基类, 来避开静态类型检查,
{
public:
virtual void put( int )// 相同签名的函数
{}
virtual ~base()= 0{} ;
} ;
class policy
{
public:
vectorvec ;// 多态数组
~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++是静态类型检查的语言, 要编写类型安全的多态静态数组,几乎是不可能的
所以你必须为每次使用不同的"同名函数"都要修改下源代码,这样很笨拙.
C#中采用委托的方式,其实和C++的typedef非常相像,都是必须先定义一个类型,然后用该类型去声明一个变量。最大的不同在赋值阶段,C++只需要简单的将函数地址赋给指针,而C#必须用new声明一个对象,并且还要求相应的函数作为形参传入。在这个阶段,似乎C#显得更为复杂。到了调用阶段,C++和C#都可以容器后加个括号就能完成调用,但C++还多了一种*的方式。