2

在什么情况下,我们在运算符重载中通过引用传递对象,为什么?另外,在什么情况下运算符重载有用(特定情况)?

编辑:语言:C++

4

3 回答 3

3

您“通过引用”传递参数要么是因为您想修改它们(这可能是您不希望运算符这样做的,见下文),要么仅仅是因为传递简单指针比复制整个对象更有效。

至于“为什么超载”,这主要是一个偏好问题。有一些经典的例子,比如有一个向量类可以让你添加向量或类似的东西——基本上,这些都是很好的例子,因为它们应用了算术运算符对一些新类的相同含义:无论你添加整数还是向量,在这两种情况下都写成“x+y”是一种自然的符号。这也是使用常量引用的经典原因——如果你写“a=b+c”,你不希望 b 或 c 被修改,并且如果你的结果是重载运算符绝对是一个好习惯正在做的是读者所期望的。

诸如智能指针(或迭代器,或其他“假装”为指针的东西)之类的东西喜欢重载诸如 -> 或 * 之类的运算符(取消引用运算符,而不是乘法)。同样的原因,这些对象伪装成指针,它们被用作指针,因此运算符重载用于使它们看起来更像指针。

我还重载了“,”运算符以将参数提供给字符串格式化对象——因为它看起来不错。出于同样的原因,STL 对 "<<" 和 ">>" 使用重载;他们认为它使事情更容易阅读。

最近,我重载了一些算术运算符和“==”,所以我可以用数学符号编写线性方程。围绕它的代码从可读的源代码构建系数矩阵,而不是要求开发人员编写一堆无意义的数字。这也是一个使用非常量引用的例子——然而,所有这些的结果是表示方程的矩阵中的一行,所以这正是读者所期望的。

基本上,坚持一个重要的规则:永远不要做任何意想不到的事情。仅当像“a + b”这样的结果符号确实是不了解重载内部的人所期望的时,才重载运算符。

于 2012-07-14T14:37:00.103 回答
0

cpp 的租户之一是用户类型应该看起来/表现得像内置类型(如 int)。

所以如果你能做到

int a = 1;
int b = 2;
int c = a + b;

那么你也应该能够做到

UserType e = ...;
UserType d = ...;
UserType f = e + d;

因此,运算符重载允许您为用户定义的类型定义运算符 +/-* 等......就像内置类型一样......

于 2012-07-14T14:21:35.040 回答
0

当您想自然地表达某种类型的对象的某些方面时,它很有用。例如,编译器知道 +、-、*、/ 如何应用于 int 和 double。但它不知道 + 如何应用于字符串(字符数组)。它不能总是连接数组,因为这将是无稽之谈。但是对于特定的数组集(char 数组),连接可以自然地用符号“+”表示,所以当我们编写(我们可能不这样做,因为我们有 std::string)某个字符串类时,我们重载了 operator+( const MyString& rhs) 将另一个字符串的内容添加到我们的字符串中。

但是运算符重载不仅可以用于您自己的类型。例如,您有一个表示 IPv4 地址的结构:

struct IpAddress
{
    unsigned int addr;
};

你需要一些东西,它可以帮助你在屏幕上打印这个结构,或者把它写到文件中。您可以添加函数 to_str() 将 addr 分解为 4 个组件并返回字符串表示,但更自然的方法是重载 ostream 的 operator<<:

ostream& operator<<(ostream& os, const IpAddress& ip)
{
    os 
        << (ip.addr >> 24) << '.' 
        << (0xff & (ip.addr >> 16)) << '.'
        << (0xff & (ip.addr >> 8)) << '.'
        << (0xff & ip.addr); 

    return os;
}

所以现在您将 IP 地址写入文件或屏幕没有问题:

IpAddress ip;
// put something to ip

cout << "your address is: " << ip << endl;

ofstream f("log.txt");
f << "address: " << ip << endl;

很自然。

ps 当然假设 sizeof(int) == 4 ;)

于 2012-07-14T15:00:13.230 回答