我正在尝试为以下方案找到重构解决方案。我有许多重复的函数,每个函数完全相同,除了在类实例上调用不同的成员函数,只在最内层范围内可用。
struct MyObject
{
void Function1() {};
void Function2() {};
void Function3() {};
void Function4() {};
};
std::vector<MyObject *> objects;
void CommandHandler1()
{
if (true) // lots of preconditions
{
size_t id = 0;
if (true) // lots of lookup code for id
{
MyObject *myObject = objects.at(id);
myObject->Function1();
}
// refresh code
}
// cleanup code
}
// another CommandHandler2, CommandHandler3, CommandHandler4, etc. doing the same thing but for a different member function.
我想避免多个CommandHandlerx的重复,因为它们非常相似。我试过的是传递一个std :: function来处理任何实例,因为我无法绑定到特定的实例。 An answer to this question意味着应该编译以下迷你程序。
#include <functional>
void CommandHandler(std::function<void(MyObject *)> func)
{
if (true) // lots of preconditions
{
size_t id = 0;
if (true) // lots of lookup code for id
{
MyObject *myObject = objects.at(id);
func(myObject);
}
}
// cleanup code
}
void MenuHandler(int chosen)
{
switch (chosen)
{
case 0: CommandHandler( &MyObject::Function1); break;
case 1: CommandHandler( &MyObject::Function2); break;
case 2: CommandHandler( &MyObject::Function3); break;
case 3: CommandHandler( &MyObject::Function4); break;
}
}
int main()
{
MyObject *obj1 = new MyObject;
MyObject *obj2 = new MyObject;
objects.push_back(obj1);
objects.push_back(obj2);
MenuHandler(1);
delete obj1; delete obj2;
return 0;
}
遗憾的是,这并不构建。我推测是因为我没有绑定特定的this
指针:
C:\ Program Files(x86)\ Microsoft Visual Studio 12.0 \ VC \ include \ functional(506):错误C2664:'void std :: _ Func_class&lt; _Ret,MyObject *&gt; :: _ Set(std :: _ Func_base&lt; _Ret,MyObject * GT; *)':不能将参数1从'_Myimpl *'转换为'std :: _ Func_base&lt; _Ret,MyObject *&gt; *'
我的问题是(1)我是否对上述std :: function尝试做错了,或者(2)是否还有其他模式可以重构这种情况?
答案 0 :(得分:3)
您的代码works with GCC,因此它很可能是MSVC实施std::function
的特性。我会提供一些解决方法。
如果函数1-4实际上都遵循相同的签名,则根本不需要std::function
,并且会有一个指向成员函数的普通旧指针:
void CommandHandler(void (MyObject::*func)())
{
if (true) // lots of preconditions
{
size_t id = 0;
if (true) // lots of lookup code for id
{
MyObject *myObject = objects.at(id);
(myObject->*func)();
}
}
// cleanup code
}
如果你确实需要一个不透明的可调用对象(例如,因为你绑定了一些参数),你应该可以使用std::mem_fn
为std::function
获取合适的初始化器:
void MenuHandler(int chosen)
{
switch (chosen)
{
case 0: CommandHandler( std::mem_fn(&MyObject::Function1)); break;
case 1: CommandHandler( std::mem_fn(&MyObject::Function2)); break;
case 2: CommandHandler( std::mem_fn(&MyObject::Function3)); break;
case 3: CommandHandler( std::mem_fn(&MyObject::Function4)); break;
}
}