[英]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.