这是一个简单的委托类,仅适用于void ClassType :: MethodType(InputType&)格式的方法,但可以很容易地扩展为更通用的函数,因为它太大而不能简单地显示。
class Delegate
{
public:
Delegate( void ) : Object( NULL ), Argument( NULL ) { }
virtual ~Delegate( void ) { }
template <class ClassType, class InputType, void (ClassType::*MethodType)( InputType )>
void Create( ClassType* SetObject, void* SetArgument = NULL )
{
Object = SetObject;
Argument = SetArgument;
StaticCall = &CallMethod<ClassType, InputType, MethodType>;
}
template <class InputType>
inline void operator()( InputType InputValue ) const
{
(*StaticCall)( Object, static_cast<void*>(InputValue) );
}
inline void operator()( void ) const
{
(*StaticCall)( Object, Argument );
}
protected:
typedef void (*FunctionCallType)( void*, void* );
void* Object;
void* Argument;
FunctionCallType StaticCall;
private:
template <class ClassType, class InputType, void (ClassType::*MethodType)( InputType )>
static inline void CallMethod( void* SetObject, void* PassArgument )
{
(static_cast<ClassType*>( SetObject )->*MethodType)( static_cast<InputType>(PassArgument) );
}
};
它很灵活,可以用来汇集回调类,但我遇到的一个问题是到目前为止它与虚拟调用(如我计划的话)相比(或者甚至更慢)如果它被使用了作为基类。我正在寻找有关如何提高性能的任何建议,因为我没有想法,即使它会影响功能。
我使用的最简单的性能测量代码(使用-O3)是:
class VirtualBase
{
public:
virtual void TestCall( int* Data ) {}
};
class VirtualTest : public VirtualBase
{
public:
VirtualTest() : Value(0) {}
void TestCall( int* Data )
{
Value += *Data;
}
private:
int Value;
};
class DelTest : public Delegate
{
public:
DelTest() : Value(0)
{
Create<DelTest, int*, &DelTest::TestCall>( this );
}
void TestCall( int* Data )
{
Value += *Data;
}
private:
int Value;
};
int main( int argc, char **argv )
{
clock_t start;
int Value = 1;
VirtualBase* NewBase = new VirtualTest;
start = clock();
for( size_t Index = 0; Index < 1000000000; ++Index )
{
NewBase->TestCall( &Value );
}
delete NewBase;
std::cout << (( std::clock() - start ) / (double)CLOCKS_PER_SEC) << std::endl;
Delegate* NewDBase = new DelTest;
start = clock();
for( size_t Index = 0; Index < 1000000000; ++Index )
{
NewDBase->operator()( &Value );
}
delete NewDBase;
std::cout << (( std::clock() - start ) / (double)CLOCKS_PER_SEC) << std::endl;
return 0;
}
我应该提一下,我希望这个类保持非模板,因为它使用回调来使用易于在单个向量中迭代的任何类。
答案 0 :(得分:0)
您可能希望查看有关CodeProject的 Lightweight Generic C++ Callbacks 文章
链接文章中的一些代码,显示了使用函数模板进行转发:
template<typename R, typename P1, typename P2>
class Callback
{
public:
typedef R (*FuncType)(void*, P1, P2);
Callback() : func(0), obj(0) {}
Callback(FuncType f, void* o) : func(f), obj(o) {}
R operator()(P1 a1, P2 a2)
{
return (*func)(obj, a1, a2);
}
private:
FuncType func;
void* obj;
};
template<typename R, class T, typename P1, typename P2, R (T::*Func)(P1, P2)>
R Wrapper(void* o, P1 a1, P2 a2)
{
return (static_cast<T*>(o)->*Func)(a1, a2);
}
class Foo
{
public:
float Average(int n1, int n2)
{
return (n1 + n2) / 2.0f;
}
};
float Calculate(int n1, int n2, Callback<float, int, int> callback)
{
return callback(n1, n2);
}
int main()
{
Foo f;
Callback<float, int, int> cb
(&Wrapper<float, Foo, int, int, &Foo::Average>, &f);
float result = Calculate(50, 100, cb);
// result == 75.0f
return 0;
}
还有一个关于stackoverflow here的精彩文章,可以让您更好地了解。