C++面向对象程序设计-北京大学-郭炜【课程笔记(六)】

C++面向对象程序设计-北京大学-郭炜【课程笔记(六)】

  • 1、可变长数组类的实现
  • 2、流插入运算符和流提取运算符的重载
    • 2.1、对形如cout << 5 ; 单个"<<"进行重载
    • 2.2、对形如cout << 5 << “this” ;连续多个"<<"进行重载
    • 详解案例

毕业论文:学习速度较慢
开始课程:P19 4-4.可变长数组类的实现
课程链接:程序设计与算法(三)C++面向对象程序设计 北京大学 郭炜
课程PPT:github提供的对应课程PPT

本节课内容相对较难理解,只做两章。

1、可变长数组类的实现

此部分内容不好🦟解释:请听老师讲解,最好自己把代码敲一遍。
P19 4-4.可变长数组类的实现

// 17.cpp
# include<iostream>
using namespace std;
class CArray
{int size;   // 数组元素的个数int *ptr;   // 指向动态分配的数组public:CArray(int s=0);  // s代表数组元素的个数,构造函数CArray(CArray & a);~CArray();void push_back(int v);  // 用于在数组尾部添加一个元素vCArray & operator = (const CArray & a);  // 用于数组对象间的赋值,深拷贝int length() {return size;}  // 返回数组元素个数// int & CArray::operator[](int i)  // 返回值为int 不行!不支持a[i] = 4int & operator[](int i)  // 返回值为int 不行!不支持a[i] = 4,所以返回值定义为引用{// 用以支持根据下表访问数组元素,// 如n=a[i]和a[i]=4;这样的语句return ptr[i];}//非引用的函数返回值不可以作为左值使用
};// 构造函数
CArray::CArray(int s):size(s)
{if(s == 0)ptr = NULL;else    ptr = new int[s];  // 动态分配一个内存空间
}// 复制构造函数(防止数组地址冲突)
CArray::CArray(CArray & a)
{if(!a.ptr){ptr = NULL;size = 0;return ;}ptr = new int[a.size];memcpy(ptr, a.ptr, sizeof(int)*a.size);   //一共拷贝sizeof(int)*a.size字节的内容size = a.size;
}// 析构函数:释放动态内存空间
CArray::~CArray()
{// []:属于双目运算符if(ptr) delete [] ptr; //释放动态分配的内存空间// 释放之前判断一下ptr是不是空指针
}CArray & CArray::operator=(const CArray & a)
{// 赋值号的作用是使用“=”左边对象里存放的数组,大小和内容都和右边的对象一样,但是存储空间是不一样的;从而实现一种深拷贝if(ptr == a.ptr)  // 防止a=a这样的复制导致出错return * this;if(a.ptr == NULL){// 如果a里面的数组是空的if(ptr) delete [] ptr;ptr = NULL;size = 0;return *this;}if(size<a.size){// 如果原有空间够大,就不用单独分配内存空间了if(ptr){delete [] ptr;}ptr = new int[a.size];}memcpy(ptr, a.ptr, sizeof(int)*a.size);size = a.size;return * this;
}   // CArray & CArray::operator=(const CArray & a)void CArray::push_back(int v)
{// 在数组尾部添加一个元素if(ptr){int * tmpPtr = new int[size+1]; //重新分配空间,采用临时的指针tmpPtr存储memcpy(tmpPtr, ptr, sizeof(int)*size);  //拷贝原数组内容delete[] ptr;   // 删除原本的ptr空间ptr = tmpPtr;  // 将ptr指向刚才零时的指针}else   // 数组本来就是空的ptr = new int[1];ptr[size++] = v; // 加入新的数组元素
}// 要编写可变长整形数组类,使之能如下使用:
int main()
{CArray a;  // 开始这里的数组是空的for(int i=0; i < 5; ++i){a.push_back(i);     // 要用动态分配的内存来存放数组元素,需要一个指针成员变量}CArray a2, a3;a2 = a;    // 要重载“=”for(int i=0; i<a.length(); ++i){cout << a2[i] << " ";   // a2是一个对象名,不是数组名,对象名加中括号需要重载[]}a2 = a3;  // a2是空的for(int i=0; i<a2.length(); ++i)  // a2.length()返回0{cout << a2[i] << " ";}a2 = a3;cout << endl;a[3] = 100;CArray a4(a);  //CArray的复制构造函数for(int i=0; i<a4.length(); ++i){cout << a4[i] << "";}return 0;
}

Debug:最难听懂的一行代码:“=”运算符重载
a2 = a; // 要重载“=”
a2 = a3;
下面给出了debug图片可供理解。
请添加图片描述
请添加图片描述
在这里插入图片描述

2、流插入运算符和流提取运算符的重载

课程链接:5-5流插入运算符和流提取运算符的重载
配合下方代码解释仔细听课,即可听懂。

问题1:cout << 5 << “this”;为什么能够成立?
问题2:cout是什么?

  • cout 是在 iostream 中定义的,ostream 类
    的对象。

问题3:“<<” 为什么能用在 cout上?

  • “<<” 能用在cout 上是因为,在iostream里对 “<<” 进行了重载。

2.1、对形如cout << 5 ; 单个"<<"进行重载

cout << 5 ; 即 cout.operator<<(5); // 表示对cout这个对象调用operator<<这个成员函数
cout << “this”; 即 cout.operator<<( “this” );

// 有可能按以下方式重载成 ostream类的成员函数:
void ostream::operator<<(int n). // n:可以表示左移参数5
{…… //输出n的代码return;
}

2.2、对形如cout << 5 << “this” ;连续多个"<<"进行重载

考虑返回值的问题,如果返回值是void,那么cout还能接着往下运算吗?显然不可以,如果返回值是cout,那么就可以继续调用重载

ostream & ostream::operator<<(int s). // 返回值为ostream的引用
{
…… //输出n的代码
return * this;   // this指针指向了成员函数所作用的对象,那么其就是cout。那么返回值就是cout的引用(&cout)
}
ostream & ostream::operator<<( const char * s )
{
…… //输出s的代码
return * this;
}

cout << 5 << “this”; 本质上的函数调用的形式是什么?
cout.operator<<(5).operator<<(“this”);

详解案例

例题:假定c是Complex复数类的对象,现在希望写“cout << c;”,就能以“a+bi”的形式输出c的值,写“cin>>c;”,就能从键盘接受“a+bi”形式的输入,并且使得c.real = a,c.imag = b。

#include<iostream>
#include<string>
#include<cstdlib>using namespace std;class Complex
{double real, imag;public:Complex(double r=0, double i=0):real(r),imag(i) {};friend ostream & operator<<(ostream & os, const Complex & c);friend istream & operator>>(istream & is, Complex & c); 
};// cout是ostream的成员函数,所以我们不能去写成ostream的成员函数(已经封装好了),只能写成全局函数;
// 又因为需要访问稀有成员变量,所以要用到友元函数
// 操作数的个数等于这个函数的参数个数。可以为Complex的对象,也可以是Complex的引用(能够节省时间和空间)
// os为cout的引用,即ostream & os = cout;,所以os等于cout;那么返回值也是ostream & os;所以返回值等于cout
ostream & operator<<(ostream & os, const Complex & c)
{os << c.real << "+" << c.imag << "i" << "i";  // 以"a+bi"的形式输出return os;
}istream & operator>>(istream & is, Complex & c)
{string s;is >> s;  // 将"a+bi"作为字符串读入,"a+bi"中间不能有空格int pos = s.find("+", 0);string sTmp = s.substr(0, pos);  // 分离出代表实部的字符串c.real = atof(sTmp.c_str());// atof库函数能将const char*指针指向的内容转换为floatsTmp = s.substr(pos+1, s.length()-pos-2);// 分离出代表虚部的字符串c.imag = atof(sTmp.c_str());return is;
};int main()
{Complex c;int n;cin >> c >> n;  cout << c << "," << n;   return 0;
}//程序运行结果可以如下:
13.2+133i 87
13.2+133i, 87

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SSL Pinning之双向认证

双向认证处理流程 概述获取证书逆向app 获取证书的KeyStore的 key通过jadx 反编译 app 获取证书&#xff1a;frida hook 证书转换命令行转换portecle 工具使用 charles 配置 p12 格式证书 概述 本篇只介绍怎么解决ssl pinning&#xff0c; 不讲ssl/tls 原理。 为了解决ssl pinn…

ELFK (Filebeat+ELK)日志分析系统

一. 相关介绍 Filebeat&#xff1a;轻量级的开源日志文件数据搜集器。通常在需要采集数据的客户端安装 Filebeat&#xff0c;并指定目录与日志格式&#xff0c;Filebeat 就能快速收集数据&#xff0c;并发送给 logstash 进或是直接发给 Elasticsearch 存储&#xff0c;性能上相…

cesium 添加动态波纹效果 圆形扩散效果 波纹材质

一、扩展材质 /*** 水波纹扩散材质* param {*} options* param {String} options.color 颜色* param {Number} options.duration 持续时间 毫秒* param {Number} options.count 波浪数量* param {Number} options.gradient 渐变曲率*/function CircleWaveMaterialProperty(opt…

CMC学习系列 (9):对侧半球可能支持中风后的恢复

对侧半球可能支持中风后的恢复 0. 引言1. 主要贡献2. 方法2.1 患者信息2.2 行为测试2.3 运动任务/实验范式 3. 结果3.1 对照参与者和卒中患者的相干图3.2 地形图上的CMC标签 4. 讨论5. 总结欢迎来稿 论文地址&#xff1a;https://www.sciencedirect.com/science/article/pii/S2…

golang 使用栈模拟计算器

思路&#xff1a; // Author sunwenbo // 2024/4/12 16:51 package mainimport ("errors""fmt""strconv" )// 使用数组来模拟一个栈的应用 type Stack struct {MaxTop int //表示栈最大可以存放数的个数Top int //表示栈底&#xff…

【方法】如何打开ZIP分卷压缩文件?

ZIP分卷压缩文件&#xff0c;是指在压缩文件时&#xff0c;将文件压缩成若干个ZIP格式的小压缩包&#xff0c;便于储存和传送&#xff0c;这些小压缩包可以被当作一个完整的文件来处理。那ZIP分卷压缩文件要怎么打开呢&#xff1f;不清楚的小伙伴一起来看看吧&#xff01; 首先…

星邦生化设备有限公司将出席2024第13届生物发酵展

参展企业介绍 宁波星邦生化设备有限公司&#xff0c;致力于发酵空气处理、发酵尾气处理及发酵罐节能环保装备的研发制造达30余年。公司拥有20多项自主开发的具有竞争力的国家发明专利技术及核心专有技术。连续三届被中国生物发酵产业协会评为——节能环保重点推荐企业。公司用…

LeetCode 678——有效的括号字符串

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 需要两个栈&#xff0c;一个用来保存左括号所在的位置索引&#xff0c;一个用来保存星号所在的位置索引。 从左往右遍历字符串&#xff0c;如果是左括号或者星号&#xff0c;则将位置索引分别入栈&#xff0c;如…

碧桂园服务:政企联合,助力秭归脐橙销售

4月9日&#xff0c;秭归县农业农村局与碧桂园服务智享楼下心选签订了秭归伦晚脐橙助农合作项目。 秭归县农业农村局现场对接碧桂园服务集团智享心选全国十二个重点区域核心业主代表&#xff0c;并授予他们“秭归伦晚脐橙推广大使”证书&#xff0c;每位代表都变成了秭归伦晚脐橙…

【Next】动态路由、加载 UI 和流式传输

动态路由 动态段作为 params 属性传递给 layout、page、route 和 generateMetadata 函数。 /app/blog/[slug]/page.tsx export default function Page({params}: {params:{slug:string}}) {return <h1>Slug Page -- {params.slug}</h1> };/app/shop/[...slug]/pa…

Chatgpt掘金之旅—有爱AI商业实战篇|播客剧本写作|(十三)

演示站点&#xff1a; https://ai.uaai.cn 对话模块 官方论坛&#xff1a; www.jingyuai.com 京娱AI 一、AI技术创业播客剧本写作服务有哪些机会&#xff1f; 人工智能&#xff08;AI&#xff09;技术作为当今科技创新的前沿领域&#xff0c;为创业者提供了广阔的机会和挑战。…

Scaffold-GS 代码阅读笔记

1. 系统启动部分 使用 python 中的 parser 库 为配置系统的参数设定, 和3DGS 类似&#xff0c;并且使用safe_state(args.quiet) 函数 为每一次的 log 输出加上对应的 时间戳 ## 配置参数的设定lp ModelParams(parser)op OptimizationParams(parser)pp PipelineParams(pars…