简体   繁体   English

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

[英]Passing a (possibly) virtual method as a function pointer in C++

I need to convert this code into a function pointer call for Visual Studio 2008. The GetValue() func could be virtual, but not always, and the GetObject() in different contexts would return different types. 我需要将此代码转换为Visual Studio 2008的函数指针调用GetValue()函数可以是虚拟的,但并非总是如此,并且在不同上下文中的GetObject()将返回不同的类型。

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

The calling function would pass in the GetObject()->GetValue (a pointer to a func + the object instance on which that function should be called), and the parameters will be supplied by the callee function: 调用函数将传入GetObject()->GetValue (指向func的指针+应在其上调用该函数的对象实例),而参数将由被调用者函数提供:

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

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

Thanks! 谢谢!

You really want std::tr1::function<int(int int)> for this job. 您确实需要std::tr1::function<int(int int)>来完成这项工作。 Check it's documentation on MSDN and you shall be a happy man. 检查它在MSDN上的文档,您将很高兴。

Your Foo needs to also take a pointer to an object of class T : 您的Foo还需要使用一个指向T类的对象的指针:

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

If GetObject() can return different types, then you will need to work with templates. 如果GetObject()可以返回不同的类型,那么您将需要使用模板。 Something like this: 像这样:

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

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

This is basically, compile time polymorphism 这基本上是编译时的多态性

EDIT : If you need to specify which function to call as well, then you can do something like this: 编辑 :如果您还需要指定要调用的函数,则可以执行以下操作:

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());
}

EDIT : What this boils down to, is you can write code like this: 编辑 :这可以归结为,您可以编写如下代码:

#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;
}

types A and B are unrelated, but i can pass a common handler to both. 类型A和类型B无关,但是我可以将通用处理程序传递给两者。 The question is, why is this necessary? 问题是,为什么这是必要的? Why not just do something like this (avoid the whole mess): 为什么不做这样的事情(避免整个混乱):

#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;
}

I don't see what you can gain by having the type, the object and the function to call all determined by the template, may as well just do it directly, or maybe with a few simple thin wrappers. 我看不到由类型,对象和函数来调用全部由模板确定的内容,或者直接使用它,或者仅使用一些简单的薄包装器,就不会得到什么。

Also, why not just have all of the types that can be returns by GetObject use a common interface that they inherit from, so you can just use virtual functions as they were intended? 另外,为什么不让GetObject可以返回的所有类型都使用它们继承自的公共接口,那么就可以按预期使用虚拟函数呢? This has a bit of a "code smell" to it... 这有点“代码味” ...

Your functions are global, therefore you object may be global, with a wrapper function: 您的函数是全局的,因此您的对象可能是带有包装函数的全局的:

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(...)

Cheers. 干杯。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM