进行一些代码维护,我发现需要简化的东西,有利于更好的阅读和更少的代码行。 请考虑以下示例类:
class MyClass
{
public:
MyClass();
MyClass(Object1* o1, Object2* o2, Object3* o3, Object4* o4);
~MyClass();
MyClass &operator=(const MyClass &other);
void copy(const MyClass &other);
bool operator==(const MyClass &other) const;
...
private:
Object1* o1 = 0;
Object2* o2 = 0;
Object3* o3 = 0;
Object4* o4 = 0;
};
此类由1到4个可选对象组成。
由于这些对象可能为null,当我来到相等运算符时,我发现了以下内容:
bool MyClass::operator==(const MyClass &other) const
{
if (o1 && (other.o1 == NULL)) return false;
if ((o1 == NULL) && other.o1) return false;
if (o1 && other.o1){ if (*o1!= *other.o1) return false; }
if (o2 && (other.o2 == NULL)) return false;
if ((o2 == NULL) && other.o2) return false;
if (o2 && other.o2){ if (*o2!= *other.o2) return false; }
if (o3 && (other.o3 == NULL)) return false;
if ((o3 == NULL) && other.o3) return false;
if (o3 && other.o3){ if (*o3!= *other.o3) return false; }
if (o4 && (other.o4 == NULL)) return false;
if ((o4 == NULL) && other.o4) return false;
if (o4 && other.o4){ if (*o4!= *other.o4) return false; }
return true;
}
如果需要同等操作员,我不想提出讨论,我只是想知道是否有办法简化上述代码。
一般来说:在等于运算符中比较对象指针的最标准和最有效的方法是什么?
答案 0 :(得分:2)
如果您真的想简化代码,请停止使用指针并实际使用optional
个对象。您可以wait for std::optional
(C ++ 17,所以只需几个月,新的编译器可能已经支持它),或者使用Boost:
#include <boost/optional.hpp>
class MyClass
{
public:
MyClass(
boost::optional<Object1> o1 = boost::none,
boost::optional<Object2> o2 = boost::none,
boost::optional<Object3> o3 = boost::none,
boost::optional<Object4> o4 = boost::none
) : o1(o1), o2(o2), o3(o3), o4(o4) {}
private:
boost::optional<Object1> o1;
boost::optional<Object2> o2;
boost::optional<Object3> o3;
boost::optional<Object4> o4;
};
或者只是轻松自己滚动。
现在你不需要所有这些操作符,或者你自己的拷贝构造函数。
与往常一样,关键在于抽象出某些逻辑,以便它可以整齐地重复使用。在这种情况下,某处仍然存在operator==
,并且某处仍然存在复制构造函数,但它在optional
类型中实现了一次并且没有#39} ; t需要为每个实例重新创建 en masse 。多个实例自然构成。
如果您真的想坚持当前的实施,至少可以缩短:
if (o1 && (other.o1 == NULL)) return false;
if ((o1 == NULL) && other.o1) return false;
if (o1 && other.o1){ if (*o1!= *other.o1) return false; }
为:
if (!o1 != !other.o1) return false;
if (o1 && (*o1 != *other.o1)) return false;
虽然它还有一点点。
答案 1 :(得分:0)
如何编写将接受字段getter的比较器?
template< typename TGetter > bool
Eq(MyClass const & left, MyClass const & right, TGetter && getter)
{
auto const p_left(getter(left));
auto const p_right(getter(right));
return((!p_left && !p_right) || (p_left && p_right && (*p_left == *p_right)));
}
bool MyClass::operator==(const MyClass &other) const
{
return
(
Eq(*this, other, [](const MyClass & inst){return inst.o1;})
&&
Eq(*this, other, [](const MyClass & inst){return inst.o2;})
&&
Eq(*this, other, [](const MyClass & inst){return inst.o3;})
&&
Eq(*this, other, [](const MyClass & inst){return inst.o4;})
);
)