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关系.事实上,遥 ...
随机推荐
- 【c++】类valarray介绍
valarray类用于处理数组中的数值,如将所有元素相加,找出最大.最小值,数组长度. 如何使用valarray类: 1.首先需要声明头文件 #include<valarray&g ...
- vue的history模式与哈希模式原理
hash模式 <!-- * @Author: dezhao.zhao@hand-china.com * @Date: 2021-10-26 17:52:25 * @Description: -- ...
- 开篇:Mirth Connect系统集成与数据交换引擎
Mirth最初的目的是作为HL7接口引擎('引擎'释意:IT方面的术语,指经包装过的函数库,方便别人调用:如搜索引擎.图形引擎.物理引擎等),HL7 v2.x和HL7 v3标准通常在医疗系统间用于系统 ...
- 力扣626(MySQL)-换座位(中等)
题目: 表: Seat 编写SQL查询来交换每两个连续的学生的座位号.如果学生的数量是奇数,则最后一个学生的id不交换. 按 id 升序 返回结果表. 查询结果格式如下所示. 示例1: 解释: 请注意 ...
- 浅谈DDD中的聚合
简介: 在我看来并不是MVC的基础上增加领域层,使用充血模型,解耦基础服务,我的代码就符合DDD了. 作者 | 李宇飞(菜尊)来源 | 阿里开发者公众号 在我看来并不是MVC的基础上增加领域层,使用充 ...
- 全方位事件监控管理,阿里云日志服务Kubernetes事件中心正式上线
2020年2月21日,阿里云日志服务Kubernetes事件中心正式上线,为Kubernetes事件提供集中化采集.存储.分析.可视化.告警等能力,帮助Kubernetes使用者快速构建准实时.高可靠 ...
- 科学地花钱:基于端智能的在线红包分配方案 (CIKM2020)
简介: 红包是电商平台重要的用户运营手段,本文将介绍1688基于端智能技术开发的two-stage红包分发方案.这一方案持续在线上生效,相较于原有算法有明显提升. 一.前言 本文是作者在1688进行新 ...
- dotnet 6 已知问题 获取 CultureInfo.NumberFormat 可能抛出 IndexOutOfRangeException 异常
本文记录一个 dotnet 6 已知问题,准确来说这是一个在 dotnet 5 引入的问题,到 dotnet 6.0.12 还没修.在获取 CultureInfo.NumberFormat 属性时,在 ...
- dotnet OpenXML 读取 PPT 形状边框定义在 Style 的颜色画刷
本文来和大家聊聊在 PPT 形状使用了 Style 样式的颜色画刷读取方法 在开始之前,期望大家已了解如何在 dotnet 应用里面读取 PPT 文件,如果还不了解读取方法,请参阅 C# dotnet ...
- Mybatis学习三(动态sql语句)
动态sql语句主要为以下语句 1.动态SQL:if 语句2.动态SQL:if+where 语句3.动态SQL:if+set 语句4.动态SQL:choose(when,otherwise) 语句5.动 ...