怎么超载运营商+?

时间:2012-05-22 19:16:52

标签: c++ operator-overloading

有人可以用初学者术语解释运算符重载的工作原理吗?我需要将“+”运算符作为成员函数重载,并链接到对象数组。我已经从谷歌中读到了一些东西,它似乎与“+”的运行方式相同而没有超载,所以我真的很困惑。

这是我到目前为止宣布的内容:

ALIST<t_type> & operator+(const t_type );

所以我在公共部分的ALIST课程中声明了这一点。 “+”运算符现在是否已重载,或者在此函数定义中是否需要执行更多操作才能使其重载?

此外,一旦它最终超载,我现在可以用它做什么?超载它有什么意义?

请用初学者的话说明,谢谢。

5 个答案:

答案 0 :(得分:3)

这是一个为什么的例子。

假设您正在实现一类特殊向量。例如Color类。 Color s基本上是具有4个值的向量,r,g,b,a。

现在我们正在编写一个图形引擎,在我们的程序中,我们经常想知道当来自两个不同源的光作用于我们正在振荡的像素时(如光线跟踪器),像素会发生什么。定义一个+运算符以评估当来自两个不同源的光被加在一起时会发生什么将是很方便的。

如果我们没有操作员,您可以在代码中写入以将两个Color添加到一起:

Color newColor = Color(
    color1.r + color2.r, 
    color1.g + color2.g,
    color1.b + color2.b,
    color1.a + color2.a
);

更糟糕的是,如果你正在密切关注光的物理特性,你可能会发现颜色不能正常添加。例如,它们可以根据某些线性函数添加,例如f(a)= a ^ 2 ...(光不做这个我不认为,它只是一个随机的例子)。

f(a) = a^2; f(b) = b^2
f(a + b) = ??
a = f(a)^.5; b = f(b)^.5
a + b = f(a)^.5 + f(b)^.5
f(a + b) = (f(a)^.5 + f(b)^.5)^2 *yada yada yada i'm terrible at math.

这意味着我们的Color添加代码现在变为

Color newColor = Color(
    pow(pow(color1.r, .5) + pow(color2.r, .5),2), 
    pow(pow(color1.g, .5) + pow(color2.g, .5),2),
    pow(pow(color1.b, .5) + pow(color2.b, .5),2),
    pow(pow(color1.a, .5) + pow(color2.a, .5),2), 
);

写出来的痛苦。 但是当然,如​​果我们采用Color类,并覆盖add运算符来为我们完成所有这些操作,在我们的代码中我们就可以编写

Color color = color1 + color2;

Color类定义中定义

Color Color::operator+(const Color &rhs) const {
     return Color(
           pow(pow(this.r, .5) + pow(rhs.r, .5),2), 
           pow(pow(this.g, .5) + pow(rhs.g, .5),2),
           pow(pow(this.b, .5) + pow(rhs.b, .5),2),
           pow(pow(this.a, .5) + pow(rhs.a, .5),2)
     ); 
}

由于我们的特殊添加代码只在一个地方,您可以更好地优化它,并且您程序其余部分的代码变得更具可读性。

至少看一下它的一种方法。在过去,我更喜欢像addLights(color1, color2)这样的函数,因为它更易于编码,同样易于阅读,并且更具可读性,因为很明显它不是传统的vector添加。我打赌你可以在你的整个职业生涯中不要超越运营商,我不认为你不会错过很多。

答案 1 :(得分:0)

如果您有自定义课程,并希望能够添加&#34;添加&#34;该类的两个实例与operator + overload一起允许您自定义两个对象的添加方式&#34;在一起。

您现在需要在.h或.cpp文件中实现operator +方法。

答案 2 :(得分:0)

到目前为止,您获得了正确的声明,然后您需要实现它,例如,通过将输入参数添加到内部管理的数组来填充正文。

如果你有这个,你可以说mylist = mylist + mytype;而不是mylist.add(mytype)。在这种情况下没什么大不了的,但如果你正在开发自然适用于标准运算符的类,如数学矩阵,向量,复数等,或者如果你在[]类中覆盖ALIST运算符它更有意义。

答案 3 :(得分:0)

默认情况下,运算符符号用于处理内置类型(int,char,string等)。

C ++的创建者不可能定义操作数应该如何适用于用户定义的类型,因此他实现了一个系统,您可以在其中重载它们并以一种在上下文中有意义的方式自己定义行为。那个对象。

你通常会像这样重载一个运算符:

中的

class MyClass {
    int a;
    MyClass(int value) : a(value) {}
    MyClass MyClass::operator+(const MyClass&) const;
}
在class.cpp中

MyClass MyClass::operator+(const MyClass& other) const
{
    return MyClass(this->a+other.a);
}

将返回一个新的MyClass,其中变量a设置为两个MyClass的值加在一起。完成后,您可以执行以下操作:

MyClass first(2);
MyClass second(5);
MyClass last = first + second;
std::cout << last.a << std::endl; // prints 7, which is the result of 2+5

operator+上没有超载MyClass,将两个MyClass添加在一起将无效。

答案 4 :(得分:0)

如前所述,必须有一个实施。仅仅对原型进行原型设计并不能让编译器为您编写操作。

如果您是初学者(或者至少在“初学者术语”中寻求答案),那么操作符重载不一定是直接进入的最佳选择在重要项目中使用。涉及到一些语义问题......因为+是一个非常抽象的符号,对于阅读代码的人来说可能意味着许多不同的东西,而更具描述性的名称可能更好。

请注意,即使标准库也不提供类似于通过+=附加到向量的内容,因为它们存储可能添加在一起的元素...或附加向量...或向元素添加元素结束...添加恶心 [双关语] 。将“添加”的定义称为最“正确”是很棘手的:

Why not overload operator+=() for std::vector?

(请注意,由于std::string不存储任意数学类型,因此不太模糊。)

搜索这些运算符方法的位置也很难,因为搜索方法没有唯一的名称。要查找调用,您必须筛选用于算术和字符串类的上下文中的+等。

除了命名问题之外,我还会提到,如果您想稍后传递其他参数,那么运算符重载将会牵连到您的手中。如果您希望每次在列表中放置某些内容时使用优先级参数进行扩展,该怎么办?有一些技巧可以解决它,例如将重载保持为默认实现以及使用参数化方法。或者您可以执行iostream对<iomanip>采用的内容:

http://www.cplusplus.com/reference/iostream/manipulators/

但它只是指出在您的域中潜入运营商重载之前应该谨慎使用的想法。要注意的另一个细微之处在于使用类的全局“朋友”函数进行重载与创建成员的重载之间的区别。这里有一个讨论......

Operator overloading : member function vs. non-member function?

重要的一点是,如果你想对操作的 left 手边出现非类(例如整数)的情况赋予意义,那么就无法添加int的方法。所以你必须让它成为一个全球性的过载。