运算符重载定义与友元函数

2019-10-22  本文已影响0人  ag4kd

运算符重载定义

returnType operator op(argument-list);

这种方式成为成员重载运算符函数

头文件

//
// Created by Biter on 2019/10/21.
//

#ifndef NDK_MYTIME_H
#define NDK_MYTIME_H

#include <iostream>

using namespace std;

class Time {
private:
    int hours;
    int minutes;
public:
    Time();

    Time(Time &time);

    Time(int h, int m = 0);

    void addMin(int m);

    void addHr(int h);

    Time sum(const Time &t) const;

    void show() const;

    void reset(int h = 0, int m = 0);

    Time operator +(const Time& time);//只看这个
    ~Time();

};

#endif //NDK_MYTIME_H

实现文件

//
// Created by Biter on 2019/10/21.
//
#include "mytime.h"


Time::Time() {
    hours = minutes = 0;
    std::cout << "默认构造函数" << std::endl;
}

Time::Time(Time &time) {
    hours = time.hours;
    minutes = time.minutes;
    std::cout << "拷贝构造函数" << std::endl;
}

Time::Time(int h, int m) {
    hours = h;
    minutes = m;

    std::cout << "双参构造函数" << std::endl;
}

Time::~Time() {
    std::cout << "析构函数" << std::endl;
}

void Time::addHr(int h) {
    hours += h;
}

void Time::addMin(int m) {
    minutes += m;
}

void Time::reset(int h, int m) {
    hours = h;
    minutes = m;
}

void Time::show() const {
    std::cout << "hours = " << hours << " ;minutes = " << minutes << std::endl;
}

Time Time::sum(const Time &t) const {
    Time time;
    std::cout << "局部函数对象的地址 = " << &time << std::endl;
    time.minutes = minutes + t.minutes;
    time.hours = hours + t.hours + time.minutes / 60;
    time.minutes %= 60;
    return time;
}

Time Time::operator+(const Time &time) {
    Time t;

    t.minutes = minutes + time.minutes;
    t.hours = hours + time.hours + t.minutes / 60;
    t.minutes %= 60;
    return t;
}

调用重载运算符

//
// Created by Biter on 2019/10/21.
//

#include "mytime.h"

int main() {
    Time time;
    std::cout << "main 局部函数对象的地址 = " << &time << std::endl;
    time.reset(2, 90);
    Time time1;
    time1.reset(1, 10);
    time1 = time1 + time;
    time1.show();
    std::cout << "main 局部函数对象的地址 = " << &time1 << std::endl;
    return 0;
}

time1 = time1 + time;实则调用time1 = time1.operator+(time);

注意,运算符op左侧是的对象是调用对象,右侧的对象是作为参数被传递的对象,即右侧为实参

友元函数

大多数运算符都可以通过成员或者非成员函数的方式来重载。

从数学定义上来讲3.25 * timetime*3.25是等价的。后者可以通过重载乘法运算符来实现,前者则无法通过成员函数重载运算符的方式来实现,因为3.25不是类对象,不能调用成员函数。由此产生问题1:重载调用问题。

非成员不是有对象调用的,它所使用的值都是显式的,比如

Time t = 3.25 * time;

该表达式与下面的调用匹配:

Time t = operator*(3.25,time);

该调用与下面的原型匹配:

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

对于非成员重载运算符来说,运算符表达式左边的操作数对应运算符函数的第一个参数,右边的操作数对应着第二个参数

非成员函数解决了调用问题,但是这样存在一个新问题,它不能访问对下的私语属性,即产生问题2,访问问题

然而,有一类特殊的函数可以访问类的私有属性,它们被称为友元函数

创建友元函数

前面讲述乘法操作符重过程中遇到的两个问题,一是操作符函数的调用问题,二是私有成员的访问问题,及其解决方案:友元函数

第一步:声明友元函数。

创建友元函数的第一步就是将其原型放在类的声明中,并在原型前面加上关键字friend

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

第二步,定义友元函数

因为不是成员函数,所以定义的时候不加类的作用域限定符,也就是函数定义前面不加Time::限定符,此外不要再定义中使用friend关键字:

友元运算符重载函数

上面提到过,对于非成员重载运算符来说,运算符表达式左边的操作数对应运算符函数的第一个参数,右边的操作数对应着第二个参数。这里只是深化以下这个应用。

重载 <<

Time trip;

重载输出流操作符,使其可以输出一个对象

cout<<trip;

1、使用成员函数重载

那么操作符左边的值必须是此类的对象,即

trip<<cout;

这种方式与以往的输出流用法有些不一致,显得编程不友好。

2、使用友元函数重载操作符

原型如下:

void operator<<(ostream & os,const Time & time);

实现如下:

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

调用

cout<<trip;

3、高级版本

满足链式调用

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

成员还是友元

成员函数重载运算符

成员函数重载运算符,其参数比操作数少一个,因为其中一个被隐式地传递的调用对象。在原型中,做操作数被隐式地传递给函数,右操作数对应着参数对应。如:

Time Time::operator+(const Time &time) {
    Time t;

    t.minutes = minutes + time.minutes;
    t.hours = hours + time.hours + t.minutes / 60;
    t.minutes %= 60;
    return t;
}

友元函数重载运算符

友元函数重载运算符,其参数有操作数的木梳一样,两个操作数都作为参数传递。在原型中,左操作数对应第一个参数,右操作数对应第二个参数。如

cout<<trip;
ostream & operator<<(ostream & os,const Time & time){
    os<<t.hours<<" houes; "<<t.minutes<<" minutes";
    return os;
}
上一篇下一篇

猜你喜欢

热点阅读