通常情况下,公有类方法是访问类对象私有部分的唯一途径。除此之外,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;
}

C++笔记(4)友元的更多相关文章

  1. C++学习笔记之友元

    一.引言 C++控制对类对象私有部分(private)的访问,通常只能通过公有的(public)类方法去访问.但是有时候这种限制太严格,不适合特定的问题,于是C++提供了另外一种形式的访问权限:友元. ...

  2. 【C/C++笔记】友元类函数

    最近学了友元,有三个用法: 1友元函数 2友元类 3友元类函数 我发现友元类函数的用法要比上两个用法要严格,不按格式写会各种出错,要把两个类都拆开来写,共分4步. 第一步: class A; //有 ...

  3. 读经典——《CLR via C#》(Jeffrey Richter著) 笔记_友元程序集

    [应用场景] 程序集A访问程序集B定义的Internal访问类型的类的成员. [使用方式] 在构建程序集B的时候,引入System.Runtime.CompilerServices,以此来添加Inte ...

  4. 初探C++运算符重载学习笔记&lt;2&gt; 重载为友元函数

    初探C++运算符重载学习笔记 在上面那篇博客中,写了将运算符重载为普通函数或类的成员函数这两种情况. 以下的两种情况发生.则我们须要将运算符重载为类的友元函数 <1>成员函数不能满足要求 ...

  5. C++学习笔记 构造&析构 友元 new&delete

    构造&析构函数 构造函数 定义:与类同名,可以有参可以无参,主要功能用于在类的对象创建时定义初始化的状态,无返回值,也不能用void修饰,构造函数不能被直接调用,必须通过new运算符在创建对象 ...

  6. C++学习笔记(十六):友元

    问题的提出: 我们已知道类具备封装和信息隐 藏的特性.只有类的成员函数才能访问类的私有成员,程式中的其他函数是无法访问私有成员的.非成员函数能够访问类中的公有成员,但是假如将数据成员都定义 为公有的, ...

  7. C++ Primer 学习笔记_53_类和数据抽象 --友元、static员

    分类 --友元.static成员 一.友元 友元机制同意一个类将对其.友元关系:一个样例 如果一个窗体管理类Window_Mgr可能须要訪问由其管理的Screen对象的内部数据.Screen应该同意其 ...

  8. 读书笔记 effective c++ Item 23 宁可使用非成员非友元函数函数也不使用成员函数

    1. 非成员非友元好还是成员函数好? 想象一个表示web浏览器的类.这样一个类提供了清除下载缓存,清除URL访问历史,从系统中移除所有cookies等接口: class WebBrowser { pu ...

  9. 《C++ Primer Plus》第15章 友元、异常和其他 学习笔记

    友元使得能够为类开发更灵活的接口.类可以将其他函数.其他类和其他类的成员函数作为友元.在某些情况下,可能需要前向声明,需要特别注意类和方法声明的顺序,以正确地组合友元.潜逃类是在其他类中生命的类,它有 ...

  10. 《C++ Primer Plus》15.1 友元 学习笔记

    15.1.1 友元类假定需要编写一个模拟电视机和遥控器的简单程序.决定定义一个Tv类和一个Remote类,来分别表示电视机和遥控器.遥控器和电视机之间既不是is-a关系也不是has-a关系.事实上,遥 ...

随机推荐

  1. VulnHub-Jangow-01-1.0.1打靶记录

    知识点 NMAP参数 -sV 获取系统信息 -sT TCP扫描可能会留下日志记录 -sC 使用默认脚本(在-A模式下不需要) -p1-xxx 扫描端口号 -p- ==>等价于 -p1-65535 ...

  2. Java实现控制台购书系统

    "感谢您阅读本篇博客!如果您觉得本文对您有所帮助或启发,请不吝点赞和分享给更多的朋友.您的支持是我持续创作的动力,也欢迎留言交流,让我们一起探讨技术,共同成长!谢谢!" 代码 im ...

  3. stm32串口晶振不对输出乱码+汇承HC-14lora模块

    最近要用到一个lora无线透传模块,然后就先用两个32开发板(用的STM32F103C8T6)试试简单的收发数据.结果,第一步串口发送一句话就寄了,我串口打印了"hi",结果出现了 ...

  4. 力扣48(java)-旋转图像(中等)

    题目: 给定一个 n × n 的二维矩阵 matrix 表示一个图像.请你将图像顺时针旋转 90 度. 你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵.请不要 使用另一个矩阵来旋转图像 ...

  5. HarmonyOS NEXT应用开发之Axios获取解析网络数据

    介绍 本示例介绍使用第三方库的Axios获取GBK格式的网络数据时,通过util实现GBK转换UTF-8格式.该场景多用于需要转换编码格式的应用. 效果图预览 使用说明 直接进入页面就可获取GBK格式 ...

  6. CDN应用进阶 | 正确使用CDN 让你更好规避安全风险

    为了帮助用户更好地了解和使用CDN产品,CDN应用实践进阶系统课程开课了.12月17日,阿里云CDN产品专家彭飞在线分享了<正确使用CDN,让你更好规避安全风险>议题,内容主要包括以下几个 ...

  7. Hologres如何支持超高基数UV计算(基于roaringbitmap实现)

    简介: 本文将会介绍Hologres基于roaringbitmap实现超高基数的UV计算 RoaringBitmap是一种压缩位图索引,RoaringBitmap自身的数据压缩和去重特性十分适合对于大 ...

  8. 分布式系统一致性测试框架Jepsen在女娲的实践应用

    ​简介: 女娲团队在过去大半年时间里持续投入女娲2.0研发,将一致性引擎和业务状态机解耦,一致性引擎可支持Paxos.Raft.EPaxos等多种一致性协议,根据业务需求支撑不同的业务状态机.其中的一 ...

  9. 阿里云IoT Studio升级版新增解决方案引擎 大幅提升方案交付效率

    简介: 8月25日,阿里云发布IoT Studio升级版,新增了解决方案引擎,让设备方案商复用之前搭建的解决方案模板进行简单的定制化修改,即可交付.使整个物联网解决方案的交付过程由几个月,缩短到几小时 ...

  10. [Caddy2] cloudflare, acme: cleaning up failed: no memory of presenting a DNS record

    使用 cloudflare 做为 DNS 之后,使用 Caddy 申请 Lets Encrypt 证书. 有时在日志里会发现一系列的提示信息: acme: use dns-01 solver acme ...