重构多个重复的函数,只在最内层作用域不同

  • 本文关键字:作用域 函数 重构 c++ c++11
  • 更新时间 :
  • 英文 :


我正试图找到一个重构解决方案以下场景。我有许多重复的函数,每个都做完全相同的事情,除了在一个类实例上调用不同的成员函数,这个类实例只在最内部作用域中可用。

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::函数来处理任何实例,因为我不能绑定到特定的实例。对这个问题的回答意味着应该编译下面的小程序。

#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 Studio12.0VCincludefunction (506): error C2664: 'void std::_Func_class<_Ret,MyObject *>::_Set(std::_Func_base<_Ret,MyObject . sh)*> *)':无法将参数1从'_Myimpl *'转换为'std::_Func_base<_Ret,MyObject *> *'

我的问题是(1)我是否在上面的std::函数尝试中做错了什么,或者(2)是否有任何其他模式可以重构这个场景?

您的代码与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_fnstd::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;
        }
    }

最新更新