C ++用循环重复代码

时间:2012-10-23 09:38:46

标签: c++ performance loops macros overloading

我不确定这是不是一个愚蠢的问题,所以如果是的话就开枪吧!

我正经常遇到这种“困境”。我在C ++中说了两个重载函数

说我们有两个 F 的重载(下面只是一个伪代码)

void F(A a, .../*some other parameters*/)
{ 
  //some code part
  //loop Starts here
  G1(a,.../* some other parameter*/)
  //loop ends here
  //some code part
}


void F(B b, .../*some other parameters*/)
{
  //some code part
  //loop Starts here
  G2(b,.../* some other parameter*/)
  //loop ends here
  //some code part
}

其中 A B 是不同的类型, G1 G2 是执行不同操作的不同功能。除 G1 G2 行之外的重载的代码部分是相同的,它们有时非常冗长。现在问题是..如何更有效地编写代码。当然,我不想重复代码(即使它很容易做到这一点,因为它只是一个复制粘贴例程)。一位朋友建议宏......但那看起来很脏。这很简单,因为如果我现在知道它是非常愚蠢的。非常感谢任何建议/帮助。

修改:对于那些想要代码示例的人,我很抱歉。这个问题实际上是抽象的,因为我遇到了不同的“相似”情况,我问自己如何使代码更短/更清洁。在大多数情况下代码很长,否则我不会在第一时间问这个问题。正如KilianDS指出的那样,确保函数本身不是很长也是很好的。但有时候这是不可避免的。在我遇到这种情况的许多情况下,循环甚至是嵌套的(即彼此之间的几个循环)和 F 的开头我们有一个循环的开始和 F 我们结束那个循环。

何塞

2 个答案:

答案 0 :(得分:7)

在这种情况下,防止代码重复的一种简单方法是使用模板。 E.g:

void G(A a,.../* some other parameter*/)
{
    G1(a,.../* some other parameter*/);
}
void G(B b,.../* some other parameter*/)
{
    G2(b,.../* some other parameter*/);
}

template <typename T>
void F(T x, .../*some other parameters*/)
{ 
  //some code part
  //loop Starts here
  G(x,.../* some other parameter*/)
  //loop ends here
  //some code part
}

请注意重载的G函数如何用于确定是调用G1还是G2。 但是,请注意,这只会阻止代码重复,而不是编译的可执行文件中的重复(因为每个模板实例化都会创建自己的代码)。

根据周围的体系结构,可能还有许多其他可行的选项(例如虚拟方法而不是G1 / G2调用,函数指针,lambda函数,如果你有C ++ 11 ......)

答案 1 :(得分:3)

最明显的解决方案是将公共代码部分分开 函数,并调用它们:

void F( A a, ... )
{
    commonPrefix(...);
    G1( a, ... );
    commonPostfix(...);
}

void F( B b, ... )
{
    commonPrefix(...);
    G2( a, ... );
    commonPostfix(...);
}

如果前缀和后缀之间共享了大量数据,那么 可以创建一个类来保存它,并使函数成员。

或者,您可以转发到模板,可能使用特征:

template <typename T>
class GTraits;

template<>
class GTraits<A>
{
    static void doG( A a, ... ) { G1( a, ... ); }
};

template <>
class GTraits<B>
{
    static void doG( B b, ... ) { G2( b, ... ): }
};

template <typename T>
void doF( T t, ... )
{
    //  ...
    GTraits<T>::doG( t, ... );
    //  ...
}

void F(A a, ...)
{
    doF( a, ... );
}

void F(B b, ...)
{
    doF( b, ... );
}

这很容易导致代码的公共部分出现 然而,重复。 (这是否是一个问题取决于 大多数情况下,我怀疑代码膨胀很小。)

编辑:

因为您说公共代码包含循环逻辑:您可以使用 模板方法模式,如:

class CommonBase
{
    virtual void doG( other_params ) = 0;
public:
    void doF()
    {
        //  prefix
        //  loop start
        doG( other_params );
        //  loop end
        //  suffix
    }
};

然后在每个函数中定义一个单独的派生类:

void F( A a ,... )
{
    class DoG : public CommonBase
    {
        A myA;
        void doG( other_params ) { G1( myA, other_params ); }
    public:
        DoG( A a ) : myA( a ) {}
    } do( a );
    do.doF();
}

你需要转发构造函数使它有点罗嗦, 但它确实保持了所有常用代码的共同点。