这里给出了加法运算符(+)的重载的3种变体。
我应该使用哪种变体?为什么?
class MyClass {
int myInteger;
double myDouble;
public:
MyClass(int i, double d) {
myInteger = i;
myDouble = d;
}
// Variation - 1
//--------------
MyClass operator +(MyClass rhsObj) {
return MyClass(this->myInteger + rhsObj.myInteger, this->myDouble + rhsObj.myDouble);
}
// Variation - 2
//--------------
MyClass &operator +(MyClass &rhsObj) {
rhsObj.myInteger = this->myInteger + rhsObj.myInteger;
rhsObj.myDouble = this->myDouble + rhsObj.myDouble;
return rhsObj;
}
// Variation - 3
//--------------
MyClass &operator +(MyClass &rhsObj) {
this->myInteger = this->myInteger + rhsObj.myInteger;
this->myDouble = this->myDouble + rhsObj.myDouble;
return *this;
}
};
int main() {
MyClass objOne(10, 10.5);
MyClass objTwo(20, 20.5);
MyClass objThree = objOne + objTwo;
}
Assignment Operator(=)应该是什么情况?应该使用哪种变体?
答案 0 :(得分:10)
取决于您的需求。
首先,关于你的版本 - 显然是
最有可能的是,Variation - 1是最受欢迎的。
为什么呢?因为副作用。如果您看到如下表达式:
a = b + c;
无论a
,b
和c
的类型是什么,您会怎么想?我认为,a
是b
和c
的总和,b
和c
未被触及,我的意思是 - 旧的价值观。 />
例如,假设:
a = 5;
b = 6;
c = a + b;
您希望a
或b
在总和之后成为11
吗? (如果您选择变体2或3,则会发生这种情况)。当然,你operator+
的不能重载int
,但这只是一个简单而直观的例子。
一项绩效改进:在您的变体1中,而不是
MyClass operator+(MyClass rhsObj)
我会用
MyClass operator+(const MyClass& rhsObj)
通过这种方式,您可以避免使用一个额外的副本+您将使用您的代码告诉“客户”,您根本不会更改rhsObj
,而只是使用其值。
答案 1 :(得分:4)
这三个+
之间存在微妙的差异
第一个变体:
// Variation - 1
//--------------
MyClass operator+(MyClass rhsObj)
{
return MyClass(this->myInteger + rhsObj.myInteger, this->myDouble + rhsObj.myDouble);
}
将MyClass
的对象作为输入,这意味着rhsObj
的副本将传递到+
,而原始对象rhsObj
保持不变。此覆盖返回新创建的MyClass
对象。
第二种变化:
// Variation - 2
//--------------
MyClass & operator+(MyClass & rhsObj)
{
rhsObj.myInteger = this->myInteger + rhsObj.myInteger;
rhsObj.myDouble = this->myDouble + rhsObj.myDouble;
return rhsObj;
}
将rhsObj
作为输入,并在方法中更新rhsObj
。
最后一个变体
// Variation - 3
//--------------
MyClass & operator+(MyClass & rhsObj)
{
this->myInteger = this->myInteger + rhsObj.myInteger;
this->myDouble = this->myDouble + rhsObj.myDouble;
return *this;
}
还引用rhsObj
作为参数,但rhsObj
未在方法内修改。相反,调用MyClass
的{{1}}对象已更新。
答案 2 :(得分:4)
你真的想要一个和三个的变体。
MyClass
的用户希望它遵循The Principle of Least Astonishment,并且永远不会期望看到由于添加而修改了右侧。使用const
更多将强制执行此操作,并将用作文档。如果您想修改左侧,请使用+=
。像这样:
// Plus: Modify neither the left nor the right
//--------------
MyClass operator +(const MyClass& rhsObj) const
{
return MyClass(myInteger + rhsObj.myInteger, myDouble + rhsObj.myDouble);
}
// Increment: Modify the left
//--------------
MyClass& operator +=(const MyClass& rhsObj)
{
myInteger += rhsObj.myInteger;
myDouble += rhsObj.myDouble;
return *this;
}
答案 3 :(得分:2)
从概念上讲,您希望返回一对新对,因此在您的情况下,第一个变体可能更好。
或许您想要返回其中一个参数,但后来我发现混淆了运算符的名称。第三种变体可能更好+=
。
答案 4 :(得分:0)
我认为变体1最好是主要原因之一:如果你只有lhs + rhs;
语句,你会期望/想要lhs
或rhs
被修改吗?我知道在大多数(所有?)情况下我可能都不会。
因此,排除了变体2和3。