我试图理解如何使用函数指针从C ++中的实例映射方法,如C#中的委托。
class FunctionalPointers
{
public:
static int IncrementCounter ( int *a, int b )
{
return *a += b;
}
int NonStaticIncrementCounter ( int *a, int b )
{
return *a += b;
}
};
//Declare a functional pointer as a separate type.
typedef int ( *AFunctionalPointer ) ( int*, int );
int _tmain(int argc, _TCHAR* argv[])
{
int a = 10;
int *ptr = &a;
*ptr = 200;
//This works as the methods are static
AFunctionalPointer funcInstance = FunctionalPointers::IncrementCounter;
int result = funcInstance( ptr, a );
//But if I try to make the same call from an
//instance of a non static method I get an error. Why ?
FunctionalPointers *functionalPointer = new FunctionalPointers();
//ERROR : Compiler says it's illegal operation.
AFunctionalPointer funcClassInstanceType = *functionalPointer->IncrementCounter;
int instanceResult = funcClassInstanceType( ptr, a );
return 0;
}
正如您在上面所看到的,如果为函数指针指定了静态方法,则它会完美地编译,但如果我尝试使用非静态方法对类的实例执行相同操作,则编译器会抛出非法操作错误。
将实例方法映射到C#中的委托非常有可能,如下面的代码段
class Program
{
static void Main( string[] args )
{
int a = 200;
int b = a;
FunctionalPointer funcInstance = new FunctionalPointer();
AFunctionalPointer degegateInstance = funcInstance.Increment;
int result = degegateInstance( 200, 200 );
}
}
public delegate int AFunctionalPointer( int a, int b );
class FunctionalPointer
{
public int Increment ( int a, int b )
{
return a += b;
}
public int Decrement( int a, int b )
{
return a -= b;
}
}
我的问题是,
这是我的知识差距还是C ++规则的一部分,它以不同的方式定义函数指针以支持实例类型。
答案 0 :(得分:4)
C ++需要成员函数的不同指针类型。 C ++ FAQ上有whole section。
使用C ++ 11中的std::function包装器可以获得类似C#的行为。
答案 1 :(得分:2)
指向类成员的指针应声明为:
int (ClassName::*FunctionPointer)(int, int);
答案 2 :(得分:1)
您不能将函数指针用作有状态委托;相反,你需要一个重载函数调用操作符operator()
的类。这可以像函数一样调用,也可以保持状态,例如调用成员函数的特定对象。
在C ++ 11中,一个选项是std::function
:
typedef std::function<int(int*,int)> delegate;
using namespace std::placeholders;
FunctionalPointers fp; // no need for "new" here
delegate d = [&](int * p, int a){fp.IncrementCounter(p,a);};
int result = d(ptr, a);
在C ++ 03中,您可以使用boost::function
和boost::bind
来实现相同的功能,或者使用重载的operator()
编写自己的类,如下所示:
class Delegate {
public:
typedef int FunctionalPointers::*member_fn(int*,int);
Delegate(FunctionalPointers * fp, member_fn fn) : fp(fp), fn(fn) {}
int operator()(int * p, int a) {return (fp->*fn)(p,a);}
private:
FunctionalPointers * fp; // Object to call member function of
member_fn fn; // Member function to call
};
FunctionalPointers fp;
Delegate d(&fp, &FunctionalPointers::IncrementCounter);
int result = d(ptr, a);
尽管您仍需要更多工作来获取多态行为或std::function
。
答案 3 :(得分:1)
成员指针使用不同的语法。以下是您修改后使用它的代码:
typedef int ( *AFunctionalPointer ) ( int*, int );
// Use this syntax to declare pointers to member functions
typedef int (FunctionalPointers::*InstFunctionalPointer) ( int*, int );
int main()
{
int a = 10;
int *ptr = &a;
*ptr = 200;
//This works as the methods are static
AFunctionalPointer funcStatic = FunctionalPointers::IncrementCounter;
int result = funcStatic( ptr, a );
InstFunctionalPointer funcInstance = FunctionalPointers::NonStaticIncrementCounter;
//Now when I try to make the same call from an
//instance of a non static method I don't get an error.
FunctionalPointers *functionalPointer = new FunctionalPointers();
// Use this syntax to call member functions through a member pointer
int instanceResult = (functionalPointer->*funcInstance)(ptr, a );
return 0;
}
答案 4 :(得分:1)
指向静态成员函数的指针与指向函数的指针基本相同。另一方面,指向非静态成员函数的指针是完全不同的动物,因为它们需要一个对象来调用该成员函数。
C#表达式funcInstance.Increment
将对象绑定到成员函数,并返回一些可以像普通函数一样调用的东西。 C ++等价物是:
#include <functional>
using namespace std::placeholders;
int main()
{
int a = 10;
int *ptr = &a;
*ptr = 200;
FunctionalPointers functionalPointer;
auto funcClassInstanceType = std::bind(
&FunctionalPointers::NonStaticIncrementCounter, functionalPointer, _1, _2);
int instanceResult = funcClassInstanceType( ptr, a );
}
答案 5 :(得分:1)
非静态方法属于不同类型。并且有一个很好的理由:它们应该在一个类的实例上运行!您可以声明指向非静态方法的指针
int (FunctionalPointers::*pointer_to_non_static_method)(int*, int)
= FunctionalPointers::NonStaticIncrementCounter;
但你需要一个物体来使用它!
另一个选择是重载班级中的operator()
:
class FunctionalPointers {
...
int operator()(int* a, int b) { return *a += b; };
...
}
你还需要一个对象来使用它:
FunctionalPointers f;
f(a,b);