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;
}
C++笔记(4)友元的更多相关文章
- C++学习笔记之友元
一.引言 C++控制对类对象私有部分(private)的访问,通常只能通过公有的(public)类方法去访问.但是有时候这种限制太严格,不适合特定的问题,于是C++提供了另外一种形式的访问权限:友元. ...
- 【C/C++笔记】友元类函数
最近学了友元,有三个用法: 1友元函数 2友元类 3友元类函数 我发现友元类函数的用法要比上两个用法要严格,不按格式写会各种出错,要把两个类都拆开来写,共分4步. 第一步: class A; //有 ...
- 读经典——《CLR via C#》(Jeffrey Richter著) 笔记_友元程序集
[应用场景] 程序集A访问程序集B定义的Internal访问类型的类的成员. [使用方式] 在构建程序集B的时候,引入System.Runtime.CompilerServices,以此来添加Inte ...
- 初探C++运算符重载学习笔记<2> 重载为友元函数
初探C++运算符重载学习笔记 在上面那篇博客中,写了将运算符重载为普通函数或类的成员函数这两种情况. 以下的两种情况发生.则我们须要将运算符重载为类的友元函数 <1>成员函数不能满足要求 ...
- C++学习笔记 构造&析构 友元 new&delete
构造&析构函数 构造函数 定义:与类同名,可以有参可以无参,主要功能用于在类的对象创建时定义初始化的状态,无返回值,也不能用void修饰,构造函数不能被直接调用,必须通过new运算符在创建对象 ...
- C++学习笔记(十六):友元
问题的提出: 我们已知道类具备封装和信息隐 藏的特性.只有类的成员函数才能访问类的私有成员,程式中的其他函数是无法访问私有成员的.非成员函数能够访问类中的公有成员,但是假如将数据成员都定义 为公有的, ...
- C++ Primer 学习笔记_53_类和数据抽象 --友元、static员
分类 --友元.static成员 一.友元 友元机制同意一个类将对其.友元关系:一个样例 如果一个窗体管理类Window_Mgr可能须要訪问由其管理的Screen对象的内部数据.Screen应该同意其 ...
- 读书笔记 effective c++ Item 23 宁可使用非成员非友元函数函数也不使用成员函数
1. 非成员非友元好还是成员函数好? 想象一个表示web浏览器的类.这样一个类提供了清除下载缓存,清除URL访问历史,从系统中移除所有cookies等接口: class WebBrowser { pu ...
- 《C++ Primer Plus》第15章 友元、异常和其他 学习笔记
友元使得能够为类开发更灵活的接口.类可以将其他函数.其他类和其他类的成员函数作为友元.在某些情况下,可能需要前向声明,需要特别注意类和方法声明的顺序,以正确地组合友元.潜逃类是在其他类中生命的类,它有 ...
- 《C++ Primer Plus》15.1 友元 学习笔记
15.1.1 友元类假定需要编写一个模拟电视机和遥控器的简单程序.决定定义一个Tv类和一个Remote类,来分别表示电视机和遥控器.遥控器和电视机之间既不是is-a关系也不是has-a关系.事实上,遥 ...
随机推荐
- VulnHub-Jangow-01-1.0.1打靶记录
知识点 NMAP参数 -sV 获取系统信息 -sT TCP扫描可能会留下日志记录 -sC 使用默认脚本(在-A模式下不需要) -p1-xxx 扫描端口号 -p- ==>等价于 -p1-65535 ...
- Java实现控制台购书系统
"感谢您阅读本篇博客!如果您觉得本文对您有所帮助或启发,请不吝点赞和分享给更多的朋友.您的支持是我持续创作的动力,也欢迎留言交流,让我们一起探讨技术,共同成长!谢谢!" 代码 im ...
- stm32串口晶振不对输出乱码+汇承HC-14lora模块
最近要用到一个lora无线透传模块,然后就先用两个32开发板(用的STM32F103C8T6)试试简单的收发数据.结果,第一步串口发送一句话就寄了,我串口打印了"hi",结果出现了 ...
- 力扣48(java)-旋转图像(中等)
题目: 给定一个 n × n 的二维矩阵 matrix 表示一个图像.请你将图像顺时针旋转 90 度. 你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵.请不要 使用另一个矩阵来旋转图像 ...
- HarmonyOS NEXT应用开发之Axios获取解析网络数据
介绍 本示例介绍使用第三方库的Axios获取GBK格式的网络数据时,通过util实现GBK转换UTF-8格式.该场景多用于需要转换编码格式的应用. 效果图预览 使用说明 直接进入页面就可获取GBK格式 ...
- CDN应用进阶 | 正确使用CDN 让你更好规避安全风险
为了帮助用户更好地了解和使用CDN产品,CDN应用实践进阶系统课程开课了.12月17日,阿里云CDN产品专家彭飞在线分享了<正确使用CDN,让你更好规避安全风险>议题,内容主要包括以下几个 ...
- Hologres如何支持超高基数UV计算(基于roaringbitmap实现)
简介: 本文将会介绍Hologres基于roaringbitmap实现超高基数的UV计算 RoaringBitmap是一种压缩位图索引,RoaringBitmap自身的数据压缩和去重特性十分适合对于大 ...
- 分布式系统一致性测试框架Jepsen在女娲的实践应用
简介: 女娲团队在过去大半年时间里持续投入女娲2.0研发,将一致性引擎和业务状态机解耦,一致性引擎可支持Paxos.Raft.EPaxos等多种一致性协议,根据业务需求支撑不同的业务状态机.其中的一 ...
- 阿里云IoT Studio升级版新增解决方案引擎 大幅提升方案交付效率
简介: 8月25日,阿里云发布IoT Studio升级版,新增了解决方案引擎,让设备方案商复用之前搭建的解决方案模板进行简单的定制化修改,即可交付.使整个物联网解决方案的交付过程由几个月,缩短到几小时 ...
- [Caddy2] cloudflare, acme: cleaning up failed: no memory of presenting a DNS record
使用 cloudflare 做为 DNS 之后,使用 Caddy 申请 Lets Encrypt 证书. 有时在日志里会发现一系列的提示信息: acme: use dns-01 solver acme ...