自学C++(4)

news2025/2/2 11:48:19

1、友元

友元的目的就是让一个函数或者类访问另一个类中private成员

1.1全局函数做友元

写法:在类外定义一个全局函数,如果这个函数访问到了类中private成员,则需要在这个类中声明这个函数为private类型。

 

 这里需要注意的是全局函数形参的写法,传入的形参可以是Person& p,也可以是Person* p

friend void showAge(Person& p);

void showAge(Person& p) {
    cout << p.age << endl;
//引用一个对象,对象调用直接用(.)
}

showAge(p);
friend void showAge(Person* p);

void showAge(Person* p) {
    cout << p->age << endl;
//指针的调用方式是->
}

showAge(&p);
//形参是指针,故传入的是地址

1.2、类做友元

基本格式和全局函数做友元差不多,就是在一个类中声明另一个类是friend类型。

#include<bits/stdc++.h>
using namespace std;
class phone{
	friend class myphone;
//声明另一个类为友元类型
	
	private:
		int price;
	public:
		phone(int x){
			price=x;
		}
}; 
class myphone{
	private:
		phone a;
	public:
		myphone(int x):a(x){
		}
		int getprice(){
			return a.price;
		}
};
int main(){
	int p;
	cin>>p;
	myphone a(p);
	cout<<a.getprice();
	return 0;
}

不过与全局函数做友元的区别是,在A类中声明B类是友元,意味着B类可以访问A类中的private成员,就说明B类中肯定包含类型为A的对象(如上面的代码中,myphone类是phone类的友元,myphone类中包含phone类型的对象 a),当然,也可以是A* 类型的对象,此时对B类实例变量进行初始化就需要写成A* p = new A,这样p就是指向一个A类型对象的指针。

1.3、成员函数做友元

基本写法和以上两种相同,不过在声明是友元时,需要额外声明这个函数是哪个类中的函数,防止误认为它是全局函数

2、运算符重载

2.1加法

通过p3=p1+p2,想实现功能:p3.m_A=p1.m_A+p2.m_A,p3.m_B=p1.m_B+p2.m_B 

但是编译器不知道怎么实现自定义类型相加。

以前我们实现上述功能是通过自定义函数(可以是成员函数或全局函数)的方式,如下:

 现在我们可以将成员函数名称改为operator+,这样调用函数就变成了Person p3 =p1.operator+(p2)

可以简写为Person p3 = p1+p2.

同理将全局函数名称改为operator+,则变成Person p3=operator+(p1,p2)

简写为Person p3 = p1 + p2

#include <iostream>
using namespace std;

class Time {

    public:
        int hours;      // 小时
        int minutes;    // 分钟

        Time() {
            hours = 0;
            minutes = 0;
        }

        Time(int h, int m) {
            this->hours = h;
            this->minutes = m;
        }

        void show() {
            cout << hours << " " << minutes << endl;
        }

        /*加号运算符重载*/
        Time operator+(Time p){
            Time temp;
            temp.minutes = minutes + p.minutes;
            temp.hours = hours + p.hours + temp.minutes/60;
            temp.minutes%=60;
            return temp;
        }
        

};

int main() {

    int h, m;
    cin >> h;
    cin >> m;

    Time t1(h, m);
    Time t2(2, 20);

    Time t3 = t1 + t2;
//也可以写成:Time t3 = t1.operator+(t2);
    t3.show();
    
    return 0;
}

运算符重载也可以发生函数重载,例如可以写一个Person p3 = p1 + 10,这时只需再定义一个函数Person operator+(Person& p1 , int num)。

2.2左移运算符重载

笔者认为这个稍微比较难理解

目的,实现利用cout<<输出自定义类型。

例如Person p3(10,20); cout<< p3;,意为输出p3的所有实例变量

下面先用全局函数来重载左移运算符

#include<iostream>
using namespace std;

class Time{
	public:
		Time(int h,int m){
			hours=h;
			mins=m;
		}
		int hours;
		int mins;
};

void operator<<(ostream& out,Time& p){
//cout是输出流对象,它的类型是ostream,
//而且全局只能存在一个输出流对象cout,故必须用引用
//当然,这里cout是形参,起的是一个别名,函数内名字可以随意更改 
//例如本例中就将cout改名为out,实际上没有任何区别 
	out<<p.hours<<endl<<p.mins; 
}

int main()
{
	Time p(6,59);
	cout<<p;
//operator<<(cout,p);
	return 0;
}

重载之后调用函数应该是operator<<(cout, p);简写为cout << p(这可类比于加法运算符重载中,

Person p3=operator+(p1,p2)简写为Person p3 = p1 + p2

然后试着用成员函数实现左移运算符重载:

#include<iostream>
using namespace std;

class Time{
	public:
		Time(int h,int m){
			hours=h;
			mins=m;
		}
		int hours;
		int mins;
		void operator<<(ostream& out){
			out<<hours<<endl<<mins<<endl;
		}
};


int main()
{
	Time p(6,59);
	p.operator<<(cout);
	p<<cout;
	return 0;
}

 可以看到,定义在成员函数中会导致一个严重问题,原本的cout<<p变成了p<<cout,虽然没有语法错误可以运行,但是这和我们标准输出的习惯十分不符。因此我们通常需要避免将左移运算符重载函数写成成员函数。

以上的重载还存在一个问题,即链式编程无法实现。我们知道,cout后面可以同时接多个<<,从而实现链式输出,但是我们上面写的函数没法实现这一功能,因为函数的返回值是void。

这个问题的解决在上一篇文章中实现了,这里我们同样地对重载函数的返回类型做出修改。

#include<iostream>
using namespace std;

class Time{
	public:
		Time(int h,int m){
			hours=h;
			mins=m;
		}
		int hours;
		int mins;
};

ostream& operator<<(ostream& out,Time& p){
//cout是输出流对象,它的类型是ostream,
//而且全局只能存在一个输出流对象cout,故必须用引用
//当然,这里cout是形参,起的是一个别名,函数内名字可以随意更改 
//例如本例中就将cout改名为out,实际上没有任何区别 
	out<<p.hours<<endl<<p.mins<<endl; 
	return out;
}


int main()
{
	Time p(6,59);
	cout<<p<<p<<p;
	return 0;
}

 因为具有输出功能的是输出流对象cout,因此返回值是输出流对象cout就能让这个返回值继续输出,从而实现链式编程,故返回值定为ostream&,引用是因为全局只能存在一个输出流对象cout

2.3自增运算符重载

通过重载自增运算符来实现++a,a++的功能。

#include<iostream>
using namespace std;

class Myint{
	public:
		Myint(int a){
			A=a;
		}
		Myint& operator++(){//实现前缀自增
//要返回引用,不能返回值,否则会拷贝一个对象返回 
			A++;
			return *this;
		}
//本来两个函数名字应该完全相同,不过这样编译器无法区别
//因此要在其中一个函数的形参里加上占位参数,用于区分 
		Myint operator++(int){//实现后缀自增 
//实现后缀自增的方法是:先保存原来的数,对这个数自增后,
//返回的是原来的数值。
//后缀自增应该返回一个值,因为如果返回引用,temp是这个
//函数里的局部变量,局部变量会被释放,返回的值就清零了。 
			Myint temp=*this;
			A++;
			return temp;
		}
		int A;
		
};


//注意这里Myint不能是Myint& p
//但是可以写成const Myint& p或Myint p
//因此C++中产生的临时变量是不可修改的常量
ostream& operator<<(ostream& out,Myint p){
	out<<p.A; 
	return out;
}

int main()
{
	Myint a(10);
	cout<<a++<<' ';
	cout<<a<<' ';
	cout<<++a<<' ';
	cout<<a; 
	return 0;
}

总结来说,前缀自增返回的是引用,后缀自增返回的是值,而且需要加上占位参数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/762534.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spark MLlib快速入门(1)逻辑回归、Kmeans、决策树、Pipeline、交叉验证

Spark MLlib快速入门(1)逻辑回归、Kmeans、决策树案例 除了scikit-learn外&#xff0c;在spark中也提供了机器学习库&#xff0c;即Spark MLlib。 在Spark MLlib机器学习库提供两套算法实现的API&#xff1a;基于RDD API和基于DataFrame API。今天&#xff0c;主要介绍下Data…

ModuleNotFoundError: No module named ‘pkg_resources‘

原因可能是因为setuptools升级版本过高&#xff0c;把setuptools降级到44.0.0及以下即可。 pip uninstall setuptoolspip install setuptools44.0.0 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

【洛谷】P3865 【模板】ST 表

先上ACcode: #include<bits/stdc.h> using namespace std; const int N1e510,M1e520; int n,m,f[N][20]; void solve(){cin>>n>>m;for(int i1;i<n;i) cin>>f[i][0];for(int j1;j<20;j)for(int i1;i(1<<j)-1<n;i)f[i][j]max(f[i][j-1],…

C\C++ 使用ping判断ip是否能连通

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan 简介&#xff1a; ping是一种用于测试网络连接的工具&#xff0c;它通过发送数据包到目标设备并等待其响应来工作&#xff0c;以检查网络是否连通。下面是例子. 效果&#xff1a; 代码…

【C语言】初阶结构体

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在回炉重造C语言&#xff08;2023暑假&#xff09; ✈️专栏&#xff1a;【C语言航路】 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你…

使用Vue-Router实现页面跳转

安装 npm install vue-router4 --save项目中新建router.js文件 import { createRouter,createWebHashHistory } from "vue-router"; import Home from "/pages/Home.vue" import Banner from "/pages/Banner.vue" import Post from "/pag…

每日一题2023.7.17|根据层序遍历构建二叉树

根据层序遍历构建二叉树 解题思路&#xff1a; 如果所给层序遍历数组非空&#xff0c;先构建出root结点并加入辅助队列qu&#xff0c;之后当qu非空时&#xff0c;每次从qu中取出一个结点node&#xff0c;从头开始取数组中的元素作为node的左右孩子结点。并将非空的左右孩子结点…

5、深入LoadBalance

一、介绍 Spring Cloud LoadBalancer是Spring Cloud官方自己提供的客户端负载均衡器,抽象和实现&#xff0c;用来替代Ribbon&#xff08;已经停更&#xff09;&#xff0c; 二、Ribbon和Loadbalance 对比 组件组件提供的负载策略支持负载的客户端Ribbon随机 RandomRule轮询 …

css的应用详解

一、css的应用 1、在标签上的应用 <img style"height: 500px; width:500px" src"/static/1.jpg" /> <div style"color:red;">祖国</div>将样式直接写在标签上 2、在head标签中应用style标签 <!DOCTYPE html> <ht…

IntelliJ IDEA 下载安装教程(详细图文)

IntelliJ IDEA 下载安装教程&#xff08;详细图文&#xff09; 简介 IDEA 全称 IntelliJ IDEA&#xff0c;是java编程语言的集成开发环境。IntelliJ在业界被公认为最好的Java开发工具 下载安装 ► 官网地址&#xff1a;https://www.jetbrains.com/idea ► 快速下载 (官方安装…

【SQL】保姆级教程:MySQL配置全过程 编辑器DBeaver的安装配置

MySQL 是最流行的关系型数据库管理系统&#xff0c;在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System&#xff1a;关系数据库管理系统)应用软件之一。 文章目录 一、什么是数据库&#xff1f;二、RDBMS 术语三、MySQL 安装四、安装DBeaver五、dbea…

Python异步编程框架asyncio使用方法

asyncio概念 Python异步编程框架asyncio是Python 3.4及以上版本提供的一个标准库&#xff0c;用于编写异步IO并发代码。asyncio提供了一种基于协程的高效的方式来实现异步编程&#xff0c;它可以使我们在单线程中处理大量的并发IO操作&#xff0c;提高程序的并发能力和性能。 …

输入 jar cvf 后指令提示‘jar‘ 不是内部或外部命令,也不是可运行的程序

输入 jar cvf 后指令提示jar 不是内部或外部命令&#xff0c;也不是可运行的程序 一堆说jdk系统环境配置的文章&#xff0c;我都看哭了&#xff0c;还好有这位老兄拯救了我&#xff01;&#xff01;&#xff01;献上地址 https://www.cnblogs.com/wadezhou/p/16647474.html 我输…

AI图像生成无需API开发连接集简云数据表,实现快速增强图片分辨率

1 场景描述 当设计接到一个需求时&#xff0c;按照常规的工作安排&#xff0c;从对接需求到最后完成效果图最短时间都要在5天左右&#xff0c;如果遇到高要求的客户或领导&#xff0c;后期还需要在电脑上进一步调整细节&#xff0c;一张成片起码要花上数小时时间去完成。 而人工…

Python_paramiko_与linux交互

一、基础功能介绍 # codingutf-8 import paramiko from time import sleep# 建立通信 transport paramiko.Transport((192.168.0.7, 22)) print(transport) # <paramiko.Transport at 0x5745ed0 (unconnected)># 建立连接 transport.connect(usernameroot, password1…

redis穿透问题

1.概述 一个热点数据在高并发情况下过期时间到了&#xff0c;会导致大量流量查询redis为null&#xff0c;进而请求数据库进行更新数据&#xff0c;从流量上来说请求打到了数据库上&#xff0c;这种情况可能会造成mysql服务崩溃。 2. 解决方式之一&#xff08;加锁解决之本地锁&…

机器人制作开源方案 | Delta型腿机器狗实现原地动作

1. 功能说明 本文示例将实现R322样机Delta型腿机器狗原地摆臂、原地圆形摆动、原地蹲起、原地踏步的功能。 原地摆臂 原地圆形摆动 原地蹲起 原地踏步 2. 电子硬件 本实验中采用了以下硬件&#xff1a; 主控板 Basra主控板&#xff08;兼容Arduino Uno&#xff09; 扩展板 Bigf…

pyspark随记

1、spark读取文件 #1.spark 读取csv custid_df spark.read.format("csv").\option("sep", ",").\option("header", True).\option("encoding", "utf-8").\schema("custid STRING").\load("/tmp/…

SQL聚合函数和窗口函数

1.创建表格插入数据 DROP TABLE IF EXISTS 学生; create table 学生 (student_id INT PRIMARY KEY,gender TEXT,city TEXT,a_score FLOAT(2),b_score FLOAT(2),weight FLOAT(2) )engineinnodb;INSERT INTO 学生 VALUES (001,female,xiameng,90.6,110.87,50.34), (002,male,gua…

应用程序发生异常,6个方法轻松解决!

“用电脑的时候大家有没有遇到过应用程序异常的情况呀&#xff01;刚刚突然遇到这种情况不知道应该怎么解决&#xff0c;请大家帮帮我吧&#xff01;” 应用程序发生异常是在使用电脑时常见的问题之一。当应用程序无法正常运行或突然崩溃时&#xff0c;它会显示一个错误消息或弹…