函数指针是否不支持C ++中的实例类型

时间:2012-03-08 13:53:48

标签: c++ oop function-pointers

我试图理解如何使用函数指针从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 ++规则的一部分,它以不同的方式定义函数指针以支持实例类型。

6 个答案:

答案 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::functionboost::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);