【问题标题】:How can I avoid this code duplication?我怎样才能避免这种代码重复?
【发布时间】:2014-05-30 19:53:52
【问题描述】:

我有两个方法,它们的代码几乎相同,除了它们调用的两个方法(以及我可以轻松参数化的一些其他细节)。但是,这些方法调用具有相同的签名,所以我想我可以将它们概括为一个方法。

class A{
    IApi* m_pApi;
    void M1();
    void M2();
public:
    void DoThings();
}

void A::M1(){
    int i;
    bool b;    
    m_pApi->method1( &i, &b );    
    //Other stuff...
}

void A::M2(){
    int i;
    bool b;    
    m_pApi->method2( &i, &b );
    //Other stuff...
}

void A::DoThings(){
    M1();
    M2();
}

我可以弄清楚如何“参数化”“其他东西”代码,但问题是对method1method2 的调用。我想我必须以某种方式使用std::bind,但我不能做这样的事情......

void A::M( std::function<void(int*,bool*)> f ){
    int i;
    bool b;
    f( &i, &b );
}

void A::DoThings(){
    M( std::bind( ???, m_pApi ) ); //M1
    M( std::bind( ???, m_pApi ) ); //M2
}

这里的问题是m_pApi 不是一个具体类(它是由一堆具体类实现的接口),所以我不确定我是否可以做通常的&amp;Class::Method 事情。有什么建议吗?

【问题讨论】:

  • 你不能只使用 if 语句和布尔参数标志吗?
  • 其实是四种方法(M1 ... M4)。我可以使用枚举,但我确信有更优雅的解决方案。
  • 您是想尝试在 m_pApi 类上创建一个外观吗?这可能会帮助*.com/questions/12662891/…
  • 我也想过使用指向成员函数的指针,但在处理继承层次结构时我从未使用过它们。如果我使用void (IApi::*)(int*, bool*),当我将它与m_pApi 结合来执行调用时,它会正确绑定吗?我去ideone做个快速测试。
  • 对不起,错误的测试用例 codepad.org/Oj08FpUS 这在 qt 中编译并输出“1 调用”和“2 调用”

标签: c++ refactoring stdbind


【解决方案1】:

使用pointers to member function

#include <iostream>
using namespace std;

struct IApi {
    void method1(int * i, bool * b) {
        *i = 1; *b = true;
    }
    void method2(int * i, bool * b) {
        *i = 2; *b = false;
    }
};

class A {
    IApi* m_pApi;
    void M(void (IApi::*)(int*, bool*));
public:
    A() : m_pApi(new IApi()) {}
    void DoThings();
};

void A::M(void (IApi::*mptr)(int*, bool*)) {
    int i;
    bool b;    
    (m_pApi->*mptr)( &i, &b );    
    cout << i << ' ' << b << endl;
}

void A::DoThings(){
    M(&IApi::method1);
    M(&IApi::method2);
}

int main() {
    A a;
    a.DoThings();
}

【讨论】:

  • +1:你打败了我,我在 ideone 做同样的事情:P