在C ++中将(可能的)虚方法作为函数指针传递

时间:2011-06-27 17:41:43

标签: c++ function-pointers

我需要将此代码转换为Visual Studio 2008的函数指针调用。GetValue() func可以是虚拟的,但并非总是如此,并且不同上下文中的GetObject()将返回不同的类型。 / p>

...
res = GetObject()->GetValue(x, y);
...

调用函数将传递GetObject()->GetValue(指向func的指针+应该调用该函数的对象实例),参数将由被调用函数提供:

void Foo(  (int T::func*)(int, int)  )
{
    ...
    res = func(x, y);
    ...
}

void Bar()
{
    Foo( & GetObject()->GetValue );
}

谢谢!

4 个答案:

答案 0 :(得分:5)

你真的希望std::tr1::function<int(int int)>完成这份工作。检查它在MSDN上的文档,你应该是一个快乐的人。

答案 1 :(得分:0)

您的Foo还需要指向类T的对象:

typedef int (T::MyMemFun*)(int, int);
void Foo(MyMemFun f, T * t)
{
    ...
    res = t->*f(x, y);
    ...
}

答案 2 :(得分:0)

如果GetObject()可以返回不同的类型,那么您将需要使用模板。像这样:

template <class T>
int Foo(const T &o) {
    return o->GetValue(x, y);
}

int Bar() {
    return Foo(GetObject());
}

这基本上是编译时多态

修改: 如果您还需要指定要调用的函数,那么您可以执行以下操作:

template <class T, int (T::*F)(int,int)>
int Foo(const T &o) {
    return (o->*F)(x, y);
}

int Bar() {
    // there is probably some template magic you can do to avoid knowing "Type" here..
    return Foo<Type, &Type::GetValue>(GetObject());
}

修改: 这可以归结为,你可以写这样的代码:

#include <iostream>

struct A {
    int GetValue(int x, int y) {
        return 42;
    }
};

struct B {
    int GetValue(int x, int y) {
        return 123;
    }
};

template <class T, int (T::*F)(int,int)>
int Foo(T &o) {
    return (o.*F)(0, 1);
}

int main() {
    A a;
    B b;
    std::cout << Foo<A, &A::GetValue>(a) << std::endl;
    std::cout << Foo<B, &B::GetValue>(b) << std::endl;
}

类型AB不相关,但我可以将公共处理程序传递给它们。问题是,为什么这有必要?为什么不做这样的事情(避免整个混乱):

#include <iostream>

struct A {
    int GetValue(int x, int y) {
        return 42;
    }
};

struct B {
    int GetValue(int x, int y) {
        return 123;
    }
};

int Foo(int x) {
    return x
}

int main() {
    A a;
    B b;
    std::cout << Foo(a.GetValue()) << std::endl;
    std::cout << Foo(b.GetValue()) << std::endl;
}

我没有看到你可以通过模型确定调用所有类型,对象和函数来获得什么,也可以直接进行,或者使用一些简单的薄包装器。

另外,为什么不只是让GetObject返回的所有类型都使用它们继承的公共接口,所以你可以按照预期使用虚函数?这有一点“代码味道”......

答案 3 :(得分:0)

您的函数是全局的,因此您的对象可能是全局的,具有包装函数:

public class MyMsgObject
{
    void ShowMsg(char[] Msg);

    // other methods
};

// ...

// this function belongs to a class, is a method
void MyMsgObject::ShowMsg(char[] Msg)
{
    cout << "Method: " << Msg <<"\n";
}

// this method doesn't belong to any class,
// its global
void GlobalShowMsg(char[] Msg)
{
    cout << "Global: " << Msg <<"\n";
}

// global var obj, before method wrapper:
MyMsgObject myGlobalObject;

void MethodWrapperShowMsg(char[] Msg)
{
    // method pointer is global,
    // your objects must be used as globals:
    myGlobalObject.ShowMsg(Msg);
}

// declare function pointer ("functor"),
// syntax is weird

typedef
    void (*MyGlobalFunctorType) (char[] Msg);

void main()
{
    // declare function pointer variable
    MyGlobalFunctorType MyGlobalFunctorVar = null;

    // test function pointer variable with global function
    MyGlobalFunctorVar = &GlobalShowMsg;
    MyGlobalFunctorVar("Hello Earth");

    // instantiate class into an object variable
    myGlobalObject = new MyMsgObject();

    // test function pointer variable with wrapper function
    MyGlobalFunctorVar = &MethodWrapperShowMsg;
    MyGlobalFunctorVar("Hello Moon");
} // void main(...)

干杯。