我希望重构c ++代码,以确定是否会减少代码行数以及最小复杂度的条件。
以下是示例:
if (xyz->a != cmd->aa)
{
xyz->a = cmd->aa;
obj->isFound = true; //common code for all ifs
}
if (xyz->b != cmd->bb)
{
xyz->b = cmd->bb;
obj->isFound = true;
}
依此类推。这里a,b,aa,bb被定义为结构元素。
另一个带有数组条件的示例:
if (abc->r16[0] != cmd->r0m)
{
abc>r16[0] = cmd->r0m;
obj->isFound = true; //some common code for all ifs
}
if (abc->r16[1] != cmd->r1m)
{
abc>r16[1] = cmd->r1m;
obj->isFound = true; //some common code for all ifs
}
对于r16 [0]到r16 [15]等等。这里r16 [15]在struct中定义。
最后一种情况适用于具有多维数组的if条件:
if (pqr->c_0_15_r_0_15[0][0] != cmd->obj0000)
{
pqr->c_0_15_r_0_15[0][0] = cmd->obj0000
obj->isFound = true; //some common code for all ifs
}
if (pqr->c_0_15_r_0_15[1][0] != cmd->obj0100)
{
pqr->c_0_15_r_0_15[1][0] = cmd->obj0100
obj->isFound = true; //some common code for all ifs
}
if (pqr->c_0_15_r_0_15[2][0] != cmd->obj0000)
{
pqr->c_0_15_r_0_15[2][0] = cmd->obj0200
obj->isFound = true; //some common code for all ifs
}
这里c_0_15_r_0_15 [2] [0]将经过[0] [0]至[15] [0],然后是[0] [1]至[15] [1],依此类推......
对于所有这样的条件情形,我会有100个if语句应该减少。我们如何重构这些代码?
答案 0 :(得分:1)
首先,在代码中找到重复项。如您所知 - 以下方案多次重复:
if (a != b)
{
a = b;
found = true;
}
所以 - 将它封装在一个函数中(模板,如果有多种类型:
template <typename Dst, typename Src>
inline void updateIfNeeded(Dst& dst, const Src& src, bool& wasNeeded)
{
if (dst != src)
{
dst = src;
wasNeeded = true;
}
}
请参阅 - 它有何帮助:
updateIfNeeded(abc->r16[0], cmd->r0m, obj->isFound);
updateIfNeeded(abc->r16[1], cmd->r1m, obj->isFound);
// ...
updateIfNeeded(pqr->c_0_15_r_0_15[0][0], cmd->obj0000, obj->isFound);
updateIfNeeded(pqr->c_0_15_r_0_15[1][0], cmd->obj0100, obj->isFound);
// ...
到目前为止 - 减少量非常大 - 并且它在此代码中的可读性更高。
我看到更多 - obj->isFound
重复多次 - 也许 - 这次在课堂上进行了一些封装:
class Updater
{
public:
bool anyUpdateWasNeeded = false;
template <typename Dst, typename Src>
void updateIfNeeded(Dst& dst, const Src& src)
{
if (dst != src)
{
dst = src;
anyUpdateWasNeeded = true;
}
}
};
你知道 - 不需要多次通过obj->isFound
:
Updater upd;
upd.updateIfNeeded(abc->r16[0], cmd->r0m);
upd.updateIfNeeded(abc->r16[1], cmd->r1m);
// ...
upd.updateIfNeeded(pqr->c_0_15_r_0_15[0][0], cmd->obj0000);
upd.updateIfNeeded(pqr->c_0_15_r_0_15[1][0], cmd->obj0100);
// ...
obj->isFound = upd.anyUpdateWasNeeded;
坦率地说,在这一点上我会考虑使用预处理器 - 我的意思是缩短所有这些数组更新 - 这是因为在左边你有数组 - 在右边你有很多相似名称的字段(&#34;索引&#34 ;名字......?)
但是使用预处理器是不好的样式 - 让我们尝试用纯C ++更新数组:
class Updater
{
public:
bool anyUpdateWasNeeded = false;
template <typename Dst, typename Src>
void updateIfNeeded(Dst& dst, const Src& src);
template <typename Dst, typename Src1, typename ...Src>
void updateArrayIfNeeded(Dst* dst, const Src1& src1, const Src& ...src)
{
updateIfNeeded(*dst, src1);
updateArrayIfNeeded(dst + 1, src...);
}
template <typename Dst>
void updateArrayIfNeeded(Dst* dst)
{
// nothing left
}
};
所以 - 这就是剩下的:
upd.updateArrayIfNeeded(abc->r16, cmd->r0m, cmd->r1m, ....);
upd.updateArrayIfNeeded(pqr->c_0_15_r_0_15[0], cmd->obj0000, cmd->obj0001, ...);
upd.updateArrayIfNeeded(pqr->c_0_15_r_0_15[1], cmd->obj0100, ...);
// ...
obj->isFound = upd.anyUpdateWasNeeded;
等等......
答案 1 :(得分:1)
你可以把它放在某个功能中,作为开始:
template<typename Lhs, typename Rhs>
void flagSetIfNEq(Lhs & lhs, Rhs const & rhs, bool & flag) {
if (lhs != rhs) {
lhs = rhs;
flag = true;
}
}
// call it like
flagSetIfNEq(xyz->a, uvw->aa, obj->found)!
我假设代码中的found
类型为bool
。
虽然如果你的代码中有“100次”,你可能应该考虑更积极的重构。
并为该功能提供更好的名称。