C++笔记(4)友元

通常情况下,公有类方法是访问类对象私有部分的唯一途径。除此之外,C++还提供了另外一种形式的访问权限:友元。

友元有三种:

  • 友元函数
  • 友元类
  • 友元成员函数

通过让函数成为类的友元,可以赋予该函数与类的成员函数相同的访问权限。

1.为何需要友元

Time Time::operator*(double n) const {
    Time mult;
    long totalminutes = hours * n * 60 + minutes * n;
    mult.minutes = totalminutes % 60;
    mult.hours = totalminutes / 60;
    return mult;
}

上述代码重载了乘法运算符,将一个Time值和一个double值结合在一起。

由于左侧的操作数是调用对象,下面的代码:

A = B * 2.75;

将被转换为下面的成员函数调用:

A = B.operator(2.75);

但是下面的语句:

A = 2.75 * B;

编译器不能使用成员函数调用来替换该表达式。

 

为了解决该问题我们可以使用非成员函数。非成员函数不是对象调用的,它使用的所有值(包括对象)都是显式参数。这样编译器可以将下面的表达式:

A = 2.75 * B;

与下面的非成员函数匹配:

A = operator(2.75, B);

该函数原型如下

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

由于非成员函数无法直接访问类的私有数据,因此引入友元函数。

2.创建友元

第一步:将其原型放在类声明中,并在声明前加上关键字friend

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

第二步:编写函数定义。不要使用Time::限定符号!不要使用关键字friend!

Time operator*(double n,const Time& t) { 
  Time mult;
  long totalminutes = t.hours * n * 60 + t.minutes * n;
  mult.minutes
= totalminutes % 60;
  mult.hours
= totalminutes / 60;
  
return mult;
}

上面的函数显式地访问t.minutes和t.hours,所以它必须是友元。

下面的版本将Time对象t作为一个整体使用,让成员函数来出路私有值因此不必是友元。

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

3.常用的友元:重载<<运算符

函数原型:

friend std::ostream & operator<<(std::ostream& os, const Time &t);

函数定义

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

operator<<()函数接受一个ostream参数和一个Time参数,表面看起来它必须同时是两个类的友元。但根据函数代码可以看出,函数访问了Time对象的各个成员,但是始终将ostream对象作为一个整体使用。因此它必须是Time类的友元。

函数返回一个指向ostream对象的引用,即返回一个指向调用对象(cout)的引用,因此可以像下面一样使用。

int x = 5;
int y = 6;
cout << x << y;

 


 

Time类:

#pragma once
#include <iostream>
class Time
{
private:
    int hours;
    int minutes;
public:
    Time();
    Time(int h, int m);
    void AddMin(int m);
    void AddHr(int h);
    void Reset(int h = 0, int m = 0);
    Time operator+(const Time &t) const;
    Time operator-(const Time &t) const;
    Time operator*(double n) const;
    friend Time operator*(double n, const Time& t);
    friend std::ostream & operator<<(std::ostream& os, const Time &t);
    void Show() const;
};

函数定义:

#include "Time.h"
#include <iostream>
Time::Time() {
    hours = 0;
    minutes = 0;
}
Time::Time(int h, int m) {
    hours = h;
    minutes = m;
}
void Time::AddMin(int m) {
    minutes += m;
    while (minutes>=60)
    {
        hours++;
        minutes -= 60;
    }

}
void Time::AddHr(int h) {
    hours += h;
}
void Time::Reset(int h, int m) {
    hours = h;
    minutes = m;
}
Time Time::operator+(const Time& t) const {
    Time sum;
    sum.minutes = minutes + t.minutes;
    sum.hours = hours + t.hours + sum.minutes / 60;
    sum.minutes %= 60;
    return sum;
}
Time Time::operator-(const Time& t) const {
    Time diff;
    int tot1, tot2;
    tot1 = hours * 60 + minutes;
    tot2 = t.hours * 60 + t.minutes;
    diff.minutes = (tot1 - tot2) % 60;
    diff.hours = (tot1 - tot2) / 60;

    return diff;
}
Time Time::operator*(double n) const {
    Time mult;
    long totalminutes = hours * n * 60 + minutes * n;
    mult.minutes = totalminutes % 60;
    mult.hours = totalminutes / 60;
    return mult;
}
void Time::Show() const {
    std::cout << hours << "h" << minutes << "min\n";
}
Time operator*(double n,const Time& t){
    return t * n;
}
std::ostream & operator<<(std::ostream & os, const Time& t) {
    os << t.hours << "hours," << t.minutes << "minutes\n";
    return os;
 }

 

posted @ 2021-11-21 19:32  湾仔码农  阅读(46)  评论(0编辑  收藏  举报