操作员移动装载的工作原理
How operator oveloading works
我有下面的代码
class rectangle
{
//Some code ...
int operator+ (rectangle r1)
{
return(r1.length + length);//Length is the 1st argument of r1, r2, r3
}
};
主功能
int main()
{
rectangle r1(10,20);
rectangle r2(40,60);
rectangle r3(30,60);
int len = r1 + r3;
}
在这里,如果我们将在operator+()
中看到,我们正在执行r1.length + length
。编译器是如何知道return语句中的第二个length
属于对象r3
而不是r1
或r2
的?我想答案可能在main()
中,我们已经写了
int len = r1 + r3;
如果是这样的话,为什么我们需要在中写入
operator+ (....)
{
r1.lenth + lenth; //Why not length + length?
}
为什么不length + length
?因为编译器已经从main()
知道first length
属于object
r1
并且2nd
属于object
r3
。
您混淆了变量名和参数名。在运算符重载中,您将参数命名为r1
:
int operator+(rectangle r1)
{
return(r1.length+length);
}
这意味着,无论传递给operator +
的参数是什么,在操作符的主体内,它都将被命名为r1
(无论其原始名称如何)。
r1.length
是参数的长度,length
是当前对象(即this->length
)的长度。
//为什么不是长度+长度?
这只会返回当前对象长度的两倍。
让我们分析一下代码:
rectangle r1(10,20);
rectangle r2(40,60);
rectangle r3(30,60);
int len = r1+r3;
最后一个调用相当于r1.operator+(r3)
。在操作符内部,length
表示r1.length
,r1.length
表示r3.length
。实际上,即使是r3.length
也不会,因为您传递的是值,并且会创建一个副本。通常的语法是:
int operator+(const rectangle& r1)
{
return(r1.length+length);
}
此外,添加矩形实际上没有意义,至少你是如何定义的。添加两个矩形会返回长度的总和,这并不直观。它至少应该返回一个不同的形状。
int len=r1+r3;
这被解决为
int len = r1.operator+(r3);
因此,该方法是在r1对象上调用的,对operator+
中成员的任何引用都将是对r1
的成员的引用,r3是该方法的实际参数。
一个对象内的每个变量都不同于另一个对象的变量。只有当你通过参数将对象传递给编译器时,编译器才会知道。它没有其他方法知道这一点。调用函数时,将在堆栈上创建对象的副本。您在参数列表中指定的名称将是编译器将使用的名称,而与您调用函数时使用的名称无关。
int operator+(rectangle r1)
{
return(r1.length+length);
}
r1 + r3; //In main
在本例中,函数调用中对象的名称为r1
。你可以给它起任何名字。编译器在main中被调用时不知道它的名称是r3
。您将从函数中返回一个整数。最好创建一个临时对象并按值返回。
运算符类似于class rectangle
的成员函数,但具有另一种调用格式。
您也可以根据其他用户的建议,将int len = r1.operator+(r3);
作为函数进行调用。
因此,当您使用类中的运算符编写操作时,编译器会尝试将调用与某些给定的运算符相匹配;在您的通话中:
int len = r1+r3;
编译器寻找一个operator+
,它返回一些可以放入int
中的东西,并接收一个作为参数的rectangle
,它找到了你的int operator+(rectangle r1)
函数;然后用CCD_ 38参数调用该函数并返回CCD_。
给int operator+(rectangle r1)
函数的参数是r3
的副本,因此,这就是为什么在r3
上操作而不是在r1
或r2
上操作。
这个问题没有提到,但我认为值得一提:
你的operator+
似乎不适合操作符通常遵循的模型,如果你要添加一个rectangle
,并从操作中获得一个不同于rectangle
的对象,它看起来不像操作符;我认为你必须思考你想要得到什么,rectangle
的总结是什么。
作为一个二进制运算符,它通常获取并返回相同类型的对象(为了在操作链中使用它),并且必须是常量,因为它不会更改对象本身:
class rectangle
{
// Reference in order to avoid copy and const because we aren't going to modify it.
// Returns a rectangle, so it can be used on operations chain.
rectangle operator+(const rectangle &r) const
{
rectangle Result;
// Do wathever you think that must be the addition of two rectangles and...
return Result;
}
};
int main()
{
rectangle r1(10,20);
rectangle r2(40,60);
rectangle r3 = r1 + r2;
// Operation chain
rectangle r4 = r1 + r2 + r3;
rectangle r5 = r1 + r2 + r3 + r4;
// Is this what you're looking for?
int width = (r1 + r3).width();
int height = (r1 + r3).height();
}
如果是一元运算符,则参数和返回值也必须是相同的类型,但返回值必须是参与操作的对象:
class rectangle
{
// Reference in order to avoid copy and const because we aren't going to modify it.
// Returns a rectangle, so it can be used on operations chain.
rectangle &operator+=(const rectangle &r) const
{
// Do wathever you think that must be the addition of two rectangles and...
return *this;
}
};
int main()
{
rectangle r1(10,20);
rectangle r2(40,60);
rectangle r3 = r1 + r2;
// Weird operation chain, but it's only an example.
rectangle r4 = (r1 += r2) += r3;
rectangle r5 = (r1 += r2) += (r3 += r4);
}
编译器需要区分矩形的长度成员变量this->length
和r1.length
。写入length + length
意味着局部作用域中的变量this->length
将用于加法的两边。
运算符重载的作用不亚于常规函数调用。
把a+b
想象成a.operator+(b)
。
除了奇怪的名字之外,该调用与a.add(b)
没有什么不同。
如果函数add
签名是int A::add(A x)
(其中A是一个类),则将b复制到x中,并在内部添加body-x,A的所有成员都可以访问。
但这对运营商来说并没有什么特别之处。它与参数传递(C++默认为"by copy")变量范围和可见性有关。
如果您能够理解这一点,那么运算符重载应该是显而易见的。如果你做不到,回到"函数、成员函数和参数",在这些概念不清楚之前不要离开那里。
- 使用移动和复制语义时函数匹配如何工作?
- 移动语义在这里如何工作?
- QObjects 被移动到 QThreads 后信号不再工作
- std::async 如何工作:为什么它会调用这么多次复制/移动?
- 隐式生成的移动构造函数在 c++ 中如何工作?
- 重构:在 CLion 中移动 (F6) - 为什么它会这样工作?
- 带有 SFML 的 c++ 中的过程无法正常工作,移动算法
- Qt - 拖动移动 q图形项不能很好地工作
- 我的 SFML/C++ 程序按预期工作,但如何使移动变慢
- 操作员移动装载的工作原理
- 绘制移动图标,它一直是最顶端的鼠标光标和工作的全屏应用程序
- 游戏引擎中的移动如何工作
- PollEvent在没有鼠标移动[SDL]的情况下无法工作
- 字符串移动构造函数是如何工作的
- 指针在整数数组上移动时如何工作
- 更新相机移动与键不工作
- 移动文本模式光标不工作
- 移动语义在矢量重定位中的工作原理
- 如何移动语义工作与unique_ptr
- 复制省略和移动语义没有按预期工作