簡體   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