C++ Primer 第7章 类 - 中(零基础学习C++,精简学习笔记)

news2024/12/24 0:29:37

在这里插入图片描述

🤖 作者简介:努力的clz ,一个努力编程的菜鸟 🐣🐤🐥
 
👀 文章专栏:C++ Primer 学习笔记
 
📔专栏简介: 本专栏是博主学习 C++ Primer 的学习笔记,因为这本书内容超级多,所以博主将其中的 重点 概括提炼出来,于是有了这个专栏的诞生。
 
C++ Primer 学习笔记 第7章 类 笔记导航 🚥🚥🚥

  1. 🥬 C++ Primer 第7章 类 - 上
  2. 🥕 C++ Primer 第7章 类 - 中 ⇦当前位置🪂
  3. 🥪 C++ Primer 第7章 类 - 下 (加班中)
  4. 🎨 C++ Primer 总目录 传送门 🏃‍🏃‍🏃‍
     

如果本篇文章对大家起到帮助的话,跪求各位帅哥美女们,求赞👍 、求收藏 👏、求关注!👀

 

第7章 类 (中)

7.3 类的其它特性

7.3.1 类成员再探

本节将会创建两个新类:Screen、Window_mgr 类 来展示类的其它特性。

 

1. 定义一个类型成员

Screen 类 表示显示器中的一个窗口。

#include <string>

using std::string;

class Screen
{
public:
    typedef string::size_type pos;

private:
    pos cursor = 0;            // 光标的位置
    pos height = 0, width = 0; // 屏幕的高和宽
    string contents;           // 保持 Screen 的内容
};

 

关于 pos 的声明有两点需要注意:

  • 可以等价第使用类型别名 代替上方代码写法;
  • 用来定义类型的成员必须先定义后使用。
class Screen
{
public:
    typedef string::size_type pos;

	// 上方代码等价于
	using pos = string::size_type;	// 使用类型别名等价地声明一个类型名字

private:
    // 略
};

 

2. Screen 类的成员函数

#include <string>

using std::string;

class Screen
{
public:
    typedef string::size_type pos;	// 定义一个类型成员

    Screen() = default; // 因为 Screen 有另一个构造函数,所以必须显式声明默认构造函数

    // 初始值列表未对 cursor 赋初值,所以会隐式地使用类内初始值
    Screen(pos ht, pos wd, char c) : height(ht), width(wd), contents(ht * wd, c) {}

    char get() const // 读取光标处的字符
    {
        return contents[cursor]; // 隐式内联
    }

    inline char get(pos ht, pos wd) const; // 显式内联

    Screen &move(pos r, pos c); // 能在之后被设为内联

private:
    pos cursor = 0;            // 光标的位置
    pos height = 0, width = 0; // 屏幕的高和宽
    string contents;           // 保持 Screen 的内容
};

 

3. 令成员作为内联函数

定义在类内部的成员函数是 自动 inline 的,例如 Screen 类 的构造函数和 get 函数。

  • 在类的 内部,可以把 inline 关键字 作为声明的一部分显式地声明成员函数;
  • 在类的 外部,可以用 inline 关键字 修饰函数的定义.
/**
 * @brief 移动光标到指定的列
 *
 * @param r
 * @param c
 * @return Screen&
 */
inline Screen &Screen::move(pos r, pos c) // 可以在函数的定义处指定inline
{
    pos row = r * width; // 计算行的位置
    cursor = row + c;    // 在行内将光标移动到指定的列
    return *this;        // 以左值的形式返回对象
}

/**
 * @brief 返回光标所指字符
 *
 * @param r
 * @param c
 * @return char
 */
char Screen::get(pos r, pos c) const // 在类的内部声明成inline
{
    pos row = r * width;      // 计算行的位置
    return contents[row + c]; // 返回给定列的字符
}

 

4. 重载成员函数

成员函数也可以和非成员函数一样进行 函数重载 ,只要函数之间 参数数量、类型 有区别即可。

 

5. 可变数据成员

当在变量声明前增加一个 mutable 关键字 ,就成为了 可变数据成员 ,其永远不会是 const
 
即使在 const成员函数 内,也可以对 可变数据成员 进行修改。

/**
 * @brief 保持一个计数值,用于记录成员函数被调用的次数
 *
 */
void Screen::some_member() const
{
    ++access_ctr; // mutable 可变数据成员
}

在这里插入图片描述

 

6. 类数据成员的初始值

下方代码中,使用一个单独的元素值对 vector 成员 执行了列表初始化,这个 Screen 的值被传递给 vector<Screen> 的构造函数,从而创建一个单元素的 vector对象

// todo 窗口管理类
class Window_mgr
{
private:
    // 这个 Window_mgr 追踪的 Screen
    // 默认情况下,一个 Window_mgr 包含一个标准尺寸
    vector<Screen> screens{Screen(24, 80, ' ')};
};

 


7.3.2 返回 *this 的成员函数

添加两个重名的 set 函数,set 成员返回值是调用 set 的对象的引用,也就是函数返回的是对象本身而非对象的副本。

/**
 * @brief 设置光标所在位置的字符
 *
 * @param c
 * @return Screen&
 */
inline Screen &Screen::set(char c)
{
    contents[cursor] = c; // 设置当前光标所在位置的新值
    return *this;         // 将this对象作为左值返回
}

/**
 * @brief 设置给定位置的字符
 *
 * @param r
 * @param col
 * @param ch
 * @return Screen&
 */
inline Screen &Screen::set(pos r, pos col, char ch)
{
    contents[r * width + col] = ch; // 设置给定位置的新值
    return *this;                   // 将this对象作为左值返回
}

在这里插入图片描述

 

1. 从const 成员函数返回 * this

接下来会添加一个 display 操作 ,负责打印 Screen 的内容,令其为一个 const 成员
 
一个 const 成员函数如果以引用的形式返回 *this,那么它的返回类型将是常量引用。

 

2. 基于 const 的重载

    /**
     * @brief 负责显示 Screen 的内容
     *
     * @param os
     */
    void do_display(ostream &os) const
    {
        os << contents;
    }

在这里插入图片描述

 

    // 根据对象是否是 const 重载了 display 函数
    Screen &display(ostream &os)
    {
        do_display(os);
        return *this;
    }

    const Screen &display(ostream &os) const
    {
        do_display(os);
        return *this;
    }

在这里插入图片描述

 


7.3.3 类类型

每个类定义了唯一的类型。即使两个类的成员列表完全一致,也是不同的类型。

struct First 
{
	int memi;
	int getMem();
};

struct Second
{
	int memi;
	int getMem();
};

First obj1;
Second obj2= boj1;	// 错误: obj1 和 obj2 的类型不同

 

类的声明

类的声明和定义可以分开进行,先声明后定义。
 
这种声明称为 前向声明,类型 Screen 在声明之后、定义之前处于 不完全类型
 
不完全类型 只能知道 Screen 是一个类类型,但不清楚类内包含哪些成员(因为还没定义)。

class Screen;	// Screen 类的声明

 


7.3.4 友元再探

除了将非成员函数定义成 友元 ,还有其它应用场景:

  • 把其它类定义成友元;
  • 把其它类的成员函数定义成友元;

 

1. 类之间的友元关系

在 Screen 类中设置 友元类 ,友元类的成员函数可以访问包括非公有成员在内的所有成员。

在这里插入图片描述

 

注意!友元关系不具备传递性
 
Screen 设置 友元类Window_mgr,如果 Window_mgr 设置 友元类 Student,但 Screen 与 Student 并不是友元关系。

// todo 窗口管理类
class Window_mgr
{
public:
    // 窗口中每个屏幕的编号
    using ScreenIndex = vector<Screen>::size_type;

    // 按照编号将指定的Screen重置为空白
    void clear(ScreenIndex);

private:
    // 这个 Window_mgr 追踪的 Screen
    // 默认情况下,一个 Window_mgr 包含一个标准尺寸
    vector<Screen> screens{Screen(24, 80, ' ')};
};

/**
 * @brief
 *
 * @param i
 */
void Window_mgr::clear(ScreenIndex i)
{
    // s是一个Screen的引用,指向我们想清空的那个屏幕
    Screen &s = screens[i];

    // 将那个选的ing的Screen重置为空白
    s.contents = string(s.height * s.width, ' ');
}

 

2. 令成员函数作为友元

设置友元类,Window_mgr 所有的成员函数都可以访问 Screen的成员变量,但可以只单独设置一个函数为友元。
 
令某个成员函数作为友元,需要按照一定的先后顺序规则:

  • 先定义 Window_mgr 类,声明 clear 函数,但不能定义;
  • 定义 Screen 类,包括对 clear 的友元声明;
  • 定义clear,此时才可以 Screen 的成员。
class Screen{
	// Window_mgr::clear 必须在 Screen 类之前被声明
	friend void Window_mgr::clear(ScreenIndex);
	
	// Screen类的剩余部分 
}

 

3. 函数重载和友元

如果一个类想把一组重载函数声明成它的友元,需要对其一个个分别声明。

 

4. 友元声明和作用域

类和非成员函数的声明不是必须在它们的友元声明之前。
 
分析下方代码,要理解友元声明的作用是影响访问权限,并非普通意义上的声明。

struct X
{
	friend void f() { /* 友元函数可以定义在类的内部 */}
	
	X() {
		f();	// 错误: f 还没被声明
	}
	void g();
	void h();
};

void X::g() {
	return f();	// 错误: f 还没有被声明
}
void f();		// 声明那个定义在 X 中的函数
void X::h() {
	return f();	// 正确: 现在 f 的声明在作用域内了
}

 


C++ Primer 学习笔记 第7章 类 笔记导航 🚥🚥🚥

  1. 🥬 C++ Primer 第7章 类 - 上
  2. 🥕 C++ Primer 第7章 类 - 中 ⇦当前位置🪂
  3. 🥪 C++ Primer 第7章 类 - 下 (加班中)
  4. 🎨 C++ Primer 总目录 传送门 🏃‍🏃‍🏃‍
     

如果本篇文章对大家起到帮助的话,跪求各位帅哥美女们,求赞👍 、求收藏 👏、求关注!👀

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

技巧:WIN10手动指定某个应用程序使用独立显卡

目录1. 背景2. 解决方法&#xff0c;假如要让剪映始终使用独立显卡2.1 步骤1&#xff0c;右击电脑桌面空白处&#xff0c;选择“显示设置”2.2 步骤2&#xff0c;拉到最下面&#xff0c;点击图形设置2.3 步骤3&#xff0c;选择桌面应用&#xff0c;点击浏览2.4 步骤4&#xff0…

领课在线教育系统源码 各行业都适用的分布式在线教育系统+支持讲师入驻功能

领课教育系统&#xff08;roncoo-education&#xff09;是基于领课网络多年的在线教育平台开发和运营经验打造出来的产品&#xff0c;致力于打造一个各行业都适用的分布式在线教育系统。系统采用前后端分离模式&#xff0c;前台采用vue.js为核心框架&#xff0c;后台采用Spring…

bash shell 无法使用 perl 正则

1.案例现象 前几天有一个小伙伴在群里求助&#xff0c;说他这个 shell 脚本有问题&#xff0c;让大家帮忙看看 #!/bin/bash regularExpression"^\[(\d)\].$" contentcat $1 for i in ${content} doif [[ $i ~ $regularExpression ]]thenecho -e "\033[32m 【 i…

一款多参数多合一的空气质量传感器【温湿度、TVOC甲醛CO2粉尘等】

档案馆库房专用的一款智能型空气质量云测仪 空气质量检测仪 空气质量传感器 环境集成传感器 集成/温湿度、粉尘PM2.5 PM10/甲醛/TVOC/CO2等高度集成的一款传感器/RS485信号输出 ◆温度测量参数: (1)温度测量范围: -40~80℃(2&#xff09;输出分辨率:0.1oC (3&#xff09;…

从零开始学架构——高性能负载均衡

高性能负载均衡 单服务器无论如何优化&#xff0c;无论采用多好的硬件&#xff0c;总会有一个性能天花板&#xff0c;当单服务器的性能无法满足业务需求时&#xff0c;就需要设计高性能集群来提升系统整体的处理性能。高性能集群的本质很简单——通过增加更多的服务器来提升系…

Pandas入门实践1 -初探

我们将开始介绍Series、DataFrame和Index类&#xff0c;它们是pandas的基本构建块&#xff0c;并展示如何使用它们。在本节结束时&#xff0c;您将能够创建DataFrame并对它们执行操作以检查和筛选数据。 DataFrame剖析 DataFrame由一个或多个Series组成。Series的名称构成列名…

( “树” 之 DFS) 111. 二叉树的最小深度 ——【Leetcode每日一题】

111. 二叉树的最小深度 给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明&#xff1a; 叶子节点是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;2…

matplotlib 笔记:subplot之间间距拉开

0 前情介绍 使用matplotlib的subplot时&#xff0c;由于默认间距不大&#xff0c;所以可能导致出的图会挤在一起 import matplotlib.pyplot as pltplt.subplot(221) plt.plot([1, 2, 3])plt.subplot(222) plt.bar([1, 2, 3], [4, 5, 6])plt.xlabel(xlabel, fontsize15, color…

码云私有仓库+宝塔面板部署WebHooks实现代码同步

权限问题&#xff0c;要分清楚两个帐号的权限www和root sudo -u www ssh -T gitgitee.com sudo -u root ssh -T gitgitee.com看清楚是用那个&#xff0c;建议用WWW帐号权限&#xff0c;不能用ROOT权限(最高权限不建议) 所以生成SSH是要注意要用那个帐号来生成&#xff1a; 一…

关于yolov7的一些理解

论文: https://arxiv.org/abs/2207.02696 Github: https://github.com/WongKinYiu/yolov7 YOLOV7的一些理解 1.摘要2.创新点3.具体工作3.1.网络结构优化3.2.辅助头训练3.3.标签分配策略3.4.重参数结构3.5.其它 1.摘要 Yolov7是Yolov4团队的作品&#xff0c;受到了yolo原作者…

Vue3瀑布流(Waterfall)

Vue2瀑布流&#xff08;Waterfall&#xff09; 可自定义设置以下属性&#xff1a; 图片数组&#xff08;images&#xff09;&#xff0c;类型&#xff1a;Array<{title: string, src: string}>&#xff0c;默认 [] 要划分的列数&#xff08;columnCount&#xff09;&a…

Linux下_多线程

线程 1. 为什么使用线程? 使用fork创建进程以执行新的任务&#xff0c;该方式的代价很高。多个进程间不会直接共享内存线程是进程的基本执行单元&#xff0c;一个进程的所有任务都在线程中执行&#xff0c;进程要想执行任务&#xff0c;必须得有线程&#xff0c;进程至少要有一…

11、响应数据

文章目录1、响应JSON1.1、引入开发场景1.2 、jackson.jar ResponseBody1、装填返回值处理器2、返回值初步处理3、获取并使用返回值处理器4、观察如何获取返回值处理器5、返回值处理器接口内部6、返回值处理器支持的类型7、返回值解析器原理1.3、HTTPMessageConverter 原理1、M…

c# 通过webView2模拟登陆小红书网页版,解析无水印视频图片,以及解决X-s,X-t签名验证【2023年4月15日】

一、c# WebView2简介 1.一开始使用WebBrowser&#xff0c;因为WebBrowser控件使用的是ie内核&#xff0c;经过修改注册表切换为Edge内核后&#xff0c; 发现Edge内核版本较低&#xff0c;加载一些视频网站提示“浏览器版本过低“&#xff0c;”视频无法加载“。 2.WebBrowser…

CentOS上PHP源码安装和配置

CentOS上PHP源码安装和配置 此文是在CentOS 7上已经部署了Nginx的基础上进行的 关于CentOS7上安装Nginx&#xff0c;可参考我之前的文章&#xff1a; CentOS上Nginx安装记录 我们现在在这个基础上安装PHP 7。 PHP里面概念挺多的&#xff0c;没想到安装这个PHP需要花那么多时…

SpringBoot 表单提交全局日期格式转换器

参考资料 SpringBoot–LocalDateTime格式转换(前端入参)SpringBoot InitBinder注解绑定请求参数 目录 一. 实现Converter<S, T>接口的方式二. 全局ControllerAdvice InitBinder注解的方式三. RequestMappingHandlerAdapter的方式四. 效果 分析 ⏹当前台的提交数据的Con…

JVM-0418

JVM-字节码篇 虚拟机体系结构 线程共享&#xff1a;堆、方法区 线程私有&#xff1a;虚拟机栈&#xff0c;本地方法栈&#xff0c;程序计数器。其中虚拟机栈中包括局部变量表&#xff0c;和操作数栈。 字节码文件概述 字节码文件是跨平台的吗&#xff1f; 是的 Java虚拟机…

Apache Log4j2(CVE-2021-4101)远程代码执行漏洞复现

文章目录前言影响范围黑盒发现复现准备JNDILADPRMI漏洞复现Dnslog数据外带使用工具进行反弹shell防御与绕过防御绕过参考前言 Apache log4j是Apache的一个开源项目&#xff0c;Java的日志记录工具(同logback)。 log4j2中存在JNDI注入漏洞&#xff0c;当程序记录用户输入的数据…

Qt Quick - FileDialog文件对话框

FileDialog文件对话框使用总结一、概述二、使用三、常用属性四、常用例子1. 单选打开文本文件2. 单选保存文本文件一、概述 FileDialog提供了一个基本的文件选择器的功能&#xff1a;它允许用户选择现有的文件或目录&#xff0c;或者创建新的文件名。 对话框最初是不可见的。…

【性能测试学习】2023最有效的7大性能测试技术(建议收藏)

进入互联网时代&#xff0c;性能测试显得越来越重要&#xff0c;移动应用、web应用和物联网应用都需要进行性能测试和性能调优&#xff0c;而进行性能和负载测试会产生了大量的数据&#xff0c;这些数据难以分析。除了数据分析&#xff0c;我们还会遇到其它一些困难和挑战。 今…