重构多个重复函数仅在最内层范围内有所不同

时间:2015-09-02 09:40:05

标签: 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 :: 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)是否还有其他模式可以重构这种情况?

1 个答案:

答案 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_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;
        }
    }