繁体   English   中英

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

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

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

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

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

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

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

谢谢!

您确实需要std::tr1::function<int(int int)>来完成这项工作。 检查它在MSDN上的文档,您将很高兴。

您的Foo还需要使用一个指向T类的对象的指针:

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

如果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;
}

类型A和类型B无关,但是我可以将通用处理程序传递给两者。 问题是,为什么这是必要的? 为什么不做这样的事情(避免整个混乱):

#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可以返回的所有类型都使用它们继承自的公共接口,那么就可以按预期使用虚拟函数呢? 这有点“代码味” ...

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

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

干杯。

暂无
暂无

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

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