0

我有以下代码

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。编译器如何知道第二个lengthreturn 语句属于 object r3not to r1or r2?我想答案可能在main()我们写的

int len = r1 + r3;

如果是这样,那我们为什么需要写

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

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

4

6 回答 6

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

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

于 2012-10-01T09:36:25.537 回答
2

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

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

r1 + r3; //In main

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

于 2012-10-01T09:36:56.953 回答
2

int len = r1+r3;

这得到解决

int len = r1.operator+(r3);

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

于 2012-10-01T09:37:35.150 回答
1

编译器需要区分矩形的长度成员变量this->length, 和r1.length。写作length + length意味着局部范围内的变量this->length, 将用于加法的双方。

于 2012-10-01T09:36:44.240 回答
1

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

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

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

int len = r1+r3;

编译器寻找一个operator+返回可以放入的东西的inta 并接收 arectangle作为参数,它找到了你的int operator+(rectangle r1)函数;然后使用参数调用此函数r3并返回int结果。

int operator+(rectangle r1)函数的参数是 so 的副本r3这就是为什么是操作 overr3而不是 over r1or r2

问题中没有提到这一点,但我认为值得一提:

似乎您operator+不适合运算符通常遵循的模型,如果您要添加 arectangle并获取与操作不同的对象,rectangle它看起来不像运算符;我认为你必须考虑你想要得到什么以及rectangles的总结是什么。

作为二元运算符,它通常获取并返回相同类型的对象(以便在操作链中使用它)并且必须是 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
    {
        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);
}
于 2012-10-01T10:37:43.483 回答
0

运算符重载的工作方式与常规函数调用一样多/不少。

认为a+b作为a.operator+(b)

除了奇怪的名字外,那个调用与a.add(b).

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

但这对运营商来说并没有什么特别之处。它与参数传递(C++ 默认为“通过复制”)变量范围和可见性有关。

如果您能理解这一点,那么运算符重载应该是显而易见的。如果不能,请退回到“函数、成员函数和参数”,在这些概念不清楚之前不要离开那里。

于 2012-10-01T10:11:30.100 回答