运算符重载的工作原理

时间:2012-10-01 09:33:54

标签: c++ operator-overloading

我有以下代码

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而不属于r1r2? 我想答案可能在我们写的main()

int len = r1 + r3;

如果是这种情况,那么为什么我们需要写入

operator+ (....) 
{
    r1.lenth + lenth; //Why not length + length?
}

为什么不length + length?因为编译器已经从main()知道first length属于object r12nd属于object r3

6 个答案:

答案 0 :(得分:5)

您将变量名称与参数名称混淆。在运算符重载中,您将参数命名为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.lengthr1.length代表r3.length。实际上,甚至不是r3.length,因为你正在通过值传递,并且将创建一个副本。通常的语法是:

int operator+(const rectangle& r1)
{
   return(r1.length+length);
}

此外,添加矩形并没有多大意义,至少你是如何定义它的。添加两个矩形返回长度之和并不直观。它至少应该返回不同的形状。

答案 1 :(得分:2)

对象内的每个变量都与另一个对象的变量不同。 只有通过参数将对象传递给它时,编译器才会知道。它没有其他方法可以了解这一点。调用该函数时,将在堆栈上创建对象的副本。您在参数列表中指定的名称将是编译器将使用的名称,无论您在调用函数时使用的名称如何。

int operator+(rectangle r1)
    {
        return(r1.length+length);
    }

r1 + r3; //In main

在此示例中,函数调用中对象的名称为r1。你可以说出任何名称。编译器在main中调用时,不知道它的名称是r3。 你从函数返回一个整数。最好创建一个临时对象并按值返回。

答案 2 :(得分:2)

  

int len = r1 + r3;

这解决了

int len = r1.operator+(r3);

因此,在r1对象上调用该方法,对operator+中成员的任何引用都将是r1的成员,而r3是该方法的实际参数。

答案 3 :(得分:1)

编译器需要将矩形的长度成员变量this->lengthr1.length区分开来。编写length + length意味着本地范围中的变量this->length将用于添加的两侧。

答案 4 :(得分:1)

运算符类似于class rectangle的成员函数,但具有另一种调用格式。

您也可以按照其他用户的建议调用函数int len = r1.operator+(r3);

因此,当您使用类中的运算符编写操作时,编译器会尝试将调用与某些给定的运算符进行匹配;在你的电话中:

int len = r1+r3;

编译器会查找operator+,该int会返回可以放入rectangle的内容并接收int operator+(rectangle r1)作为参数,并找到您的r3函数;然后使用int参数调用此函数并返回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(); } 的概要是什么。

作为binary operator,它通常会获取并返回相同类型的对象(为了在操作链中使用它),并且必须是const,因为它不会更改对象本身:

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);
}

如果它是unary operator,则参数和返回值也必须是同一类型,但返回值必须是参与操作的对象:

{{1}}

答案 5 :(得分:0)

运算符重载不会比常规函数调用更多/不少。

a+b视为a.operator+(b)

除了奇怪名称之外,该呼叫与a.add(b)中没有区别。

如果函数add签名是int A::add(A x)(其中A是一个类),则b被复制到x中,并且-inside add body-x和a的所有成员都可以访问。

但这与运营商没有什么特别之处。它涉及参数传递(C ++默认为“by copy”)变量范围和可见性。

如果你能理解,运算符重载应该是显而易见的。如果不能,请退回到“功能,成员函数和参数”,并且不要离开那里,直到这些概念不明确。