相同的代码散落在周围

时间:2015-03-21 16:29:55

标签: c++

有人能想出一种干净,优雅的方法来避免下面两个函数的重复(除了为每个相同的代码块编写辅助函数,还是使用宏)?

void foo (bool b) {
    const int num = std::rand() % 5;
    // code block A
    if (b) {
        // code block B
    }
    else {
        // code block C
    }
    // code block D
    const int number = num + 1;
    // code block E
}

void bar (bool b) {
    const int num = std::rand() % 5;
    // code block A
    // code block C  // code block B not used (bool b used elsewhere though)
    // code block D
    const int number = num < 10 ? num + 1 : 0;
    // code block E
}

一般来说,对待这样的事情最好的方法是什么?

想法:仅处理不同的部分。像

这样的东西
enum {Foo, Bar};

template <int N>
struct FooBar {
    void operator()(bool b) {
        const int num = std::rand() % 5;  // Some random number
        // code block A
        if (b) {
            // code block B
        }
        else {
            // code block C
        }
        // code block D
        const int number = get_number(num);
        // code block E
    }
  private:  
    int number(int) const;
};

template<> int FooBar<Foo>::get_number (int num) const {return num + 1;}
template<> int FooBar<Bar>::get_number (int num) const {return num < 10 ? num + 1 : 0;}

3 个答案:

答案 0 :(得分:3)

将foo和bar组合成一个带有两个参数的函数:bool bbool qq的值将决定此新函数的行为是否与foo或bar相同。

答案 1 :(得分:2)

如果在两个单独的函数中有两个相同的代码片段,唯一的方法来摆脱重复是将它们放在一个新函数(当然,还是一个宏)中。

既干净又优雅。那就是你应该做的。

答案 2 :(得分:0)

只是抛出一个似乎有用的想法。不确定它是否过于激进。其他人会这样做吗?

enum {Foo, Bar};

template <int N>
struct FooBar {
    void operator()(bool b) const {
        const int num = std::rand() % 5;  // Some random number
        // code block A
        check_bool(b);
        // code block D
        const int number = get_number(num);
        // code block E
    }
  private:  
    int get_number(int) const;
    void check_bool (bool b) const;
    void code_block_c() const {
        // code block C
    }
};

template<> void FooBar<Foo>::check_bool (bool b) const {
    if (b) {
        // code block B
    }
    else
        code_block_c();
}

template<> int FooBar<Foo>::get_number (int num) const {return num + 1;}

template<> void FooBar<Bar>::check_bool (bool) const {code_block_c();}

template<> int FooBar<Bar>::get_number (int num) const {return num < 10 ? num + 1 : 0;}

void foo (bool b) {FooBar<Foo>()(b);}
void bar (bool b) {FooBar<Bar>()(b);}

int main() {
    for (int i = 0; i < 100000000; i++) {
        foo(true);  bar(true);
        foo(false);  bar(false);
    }
}
// 5.548 seconds

// The following alternative results in no time difference really:
//FooBar<Foo> foo_;
//FooBar<Bar> bar_;
//void foo (bool b) {foo_(b);}
//void bar (bool b) {bar_(b);}

建议使用另一个bool参数:

void foo_bar (bool b, bool q) {
    const int num = std::rand() % 5;
    // code block A
    if (q) {
        if (b) {
            // code block B
        }
        else {
            // code block C
        }
    }
    else
        // code block C
    // code block D
    const int number = q ? num + 1 : (num < 10 ? num + 1 : 0);
    // code block E
}

void foo (bool b) {foo_bar(b, true);}

void bar (bool b) {foo_bar(b, false);}

int main() {
    for (int i = 0; i < 100000000; i++) {
        foo(true);  bar(true);
        foo(false);  bar(false);
    }
}
// 4.724 seconds

尽管if-checks不断检查,但他们建议的解决方案执行速度要快一些。