《C++ Primer Plus》中的运算符重载

加法运算符重载

Time operator+(const Time & t) const;

函数表示法

total = coding.operatot+(fixing);

operator+()由Time对象coding调用,将Time对象fixing作为参数,并返回一个Time对象total。

运算符表示法

total = coding + fixing;

在运算符表示法中,运算符左侧的对象coding是调用对象,运算符右边的对象fixing是作为参数被传递的对象。

将两个以上对象相加

t4 = t1 + t2 + t3;

等价于

t4 = t1.operator+(t2 + t3);

等价于

t4 = t1.operator+(t2.operator+(t3)); 

即最后的返回值为t1、t2、t3之和。

减法运算符重载

Time operator-(const Time & t) const

乘法运算符重载

Time operator*(double n) const;

友元

重载的乘法与其他两种重载运算的差别在于,它使用了两种不同的类型。符号左侧的操作数是调用对象,则只能将类对象置于符号左侧,限制了该运算符的使用方法。因此,若实现符号左侧的操作数为非类对象的乘法,需要使用如下的函数原型:

friend Time operator*(double m, const Time & t);

此函数为非成员函数,但又可访问类的私有数据,称为友元函数。

也可以使用非友元方式:

Time operator*(double m, const Time & t)
{
    return t * m;
}

原来的版本显示访问类的私有数据,因此必须是友元。而此版本将Time对象t作为一个整体使用,反转操作数顺序后让作为成员函数的重载乘法运算符函数来处理私有值,因此不必是友元函数。但不妨也将其作为友元,既使其成为正式接口的组成部分,又可在以后需要直接访问私有数据时改函数定义而不必修改原型。

重载<<运算符

可以对<<运算符进行重载,使之能与cout一起来显示对象的内容。cout是一个ostream类对象,它是智能的,能够识别所有的C++基本类型。这是因为对于每种基本类型,ostream类声明中都包含了相应的重载operator<<()定义。要使cout能识别Time对象,一种方法是将一个新的函数运算符定义添加到ostream类声明中。但修改iostream文件是个危险的主意,这样做会在标准接口上浪费时间。相反,通过Time类声明来让类知道如何使用cout。通过友元函数,像下面这样重载<<运算符:

void operator<<(ostream & os, const Time & t)

但此种方式无法连续使用<<,形如:

cout << x << y;

上述代码等同于:

(cout << x) << y;

由于要求<<运算符左侧是一个ostream对象,cout << x满足此要求,但<< y左侧也应是ostream对象,故ostream类将operator<<()函数实现为返回一个指向ostream对象的引用,具体的说,它返回一个指向调用对象(这里是cout)的引用。因此,cout << x成为ostream对象cout,从而可位于<<运算符的左侧。修改operator<<()函数,使其返回ostream对象的引用:

ostream & operator<<(ostream & os, const Time & t)
{
    os << t.hours << " hours, " << t.minutes << " minutes";
    return os;
}

即可连续使用重载<<运算符。注意,operator<<()需为友元函数。

重载一元负号运算符

Vector operator-() const;

转换函数

构造函数只用于从某种类型到类类型的转换。要进行相反的转换,必须使用特殊的C++运算符函数——转换函数。

  • 转换函数必须是类方法
  • 转换函数不能指定返回类型
  • 转换函数不能有参数

转换函数原型如下:

operator double();

重载赋值运算符

默认的赋值运算符由于浅复制可能会导致数据受损,解决办法是提供赋值运算符(进行深度复制)定义:

  • 由于目标对象可能引用了以前分配的数据,所以函数应使用delete[]来释放这些数
  • 函数应当避免将对象赋给自身;否则,给对象重新赋值前,释放内存操作可能删除对象的内容
  • 函数通过返回一个指向调用对象的引用,可以像常规赋值操作那样,连续进行赋值
String & String::operator=(const String & st)
{
    if (this == &st)
        return *this;
    delete [] str;
    len = st.len;
    str = new char [len + 1];
    std::strcpy(str, st.str);
    return *this;
}

重载中括号运算符

在C++中,两个中括号组成一个运算符——中括号运算符,可以使用方法operator[]()来重载该运算符。通常,二元C++运算符位于两个操作数之间,但对于中括号运算符,一个操作数位于第一个中括号的前面,另一个操作数位于两个中括号之间。因此,在表达式city[0]中,city是第一个操作数,[]是运算符,0是第二个操作数。

char & String::operator[](int i)
{
    return str[i];
}
posted @ 2020-06-29 15:19  溪嘉嘉  阅读(359)  评论(0编辑  收藏  举报