《C++ primer plus》精炼(OOP部分)——对象和类(2)

news2025/1/24 22:43:38

“学习是人类成长的喷泉。” - 亚里士多德

文章目录

  • 内联函数
  • 对象的方法和属性
  • 构造函数和析构函数
    • 构造函数的种类
    • 使用构造函数
    • 析构函数
    • 列表初始化
  • const成员函数
  • this指针
  • 对象数组
  • 类作用域
    • 作用域为类的常量
    • 类作用域内的枚举

内联函数

定义位于类声明中的函数自动成为内联函数。有两种方法可以成为内联函数:

  1. 将函数定义置于类声明。
  2. 在类定义中加上inline关键字。

注意,只有足够短小的函数才能被当作内联函数处理。当一个函数被定义为内联函数时,编译器在调用这个函数不会真正进入到这个函数中,而是直接用函数体来替换函数名进行处理,这样就省去了进入函数所花费到时间开销;但因为这种处理方式需要编译器对代码重新进行编译,所以只有足够简单的函数才能作为内联函数。上一篇文章中的set_tot()函数就是内联函数。

对象的方法和属性

系统为每一个对象分配一块存储空间,这个空间内分配着这个对象的属性值,但方法并不存在这块空间中,作为所有对象的公用代码段,它单独存在一块空间中并被所有对象一起调用。详细解释将留给下文,现在只需知道方法和属性不共同存储在一个地方即可。

构造函数和析构函数

为了让对象在构建的时候顺便完成指定的行为,比如打印提示语或进行属性变量的初始化,我们可以自己在类中写构造函数。
构造函数在构造对象时自动调用,一个类中必须有构造函数,如果程序员没有自己编写,编译器会帮程序员加上一个默认构造函数:

class Stock
{
	//编译器默认添加的构造函数
	Stock(){
		
	};
};

构造函数有两个特征:

  1. 函数名与类相同
  2. 没有返回值

构造函数的种类

构造函数可分为三类:

  1. 默认构造函数,即编译器自动加的函数。
  2. 带参数的构造函数:顾名思义,带有参数。
class Stock
{
	int i_;//沿用书中的命名习惯,在属性最后加一个下划线
	//带有参数的构造函数
	Stock(int i){
		i_=i;//可以像普通函数一样使用传入的参数
	};
	//可以写不止一个构造函数,也就是构造函数重载
	Stock(float i){
		cout<<i;//这次没有用参数初始化,而是直接打印了
	}
};
  1. 拷贝构造函数:传入一个该类的对象作为参数。
class Stock{
	int i_;
	//以一个该类(Stock类)的对象作为参数
	Stock(Stock s){
		i_=s.i_;//利用.运算符调用所传入对象的属性进行初始化
		cout<<s.i_;//当然也可以打印
	}
}

在编写构造函数时,如果想编写第二种和第三种构造函数,则必须先编写默认构造函数,且此时编译器不会自动提供默认构造函数。
注意,给构造函数传参时,不要让参数名和属性变量名一致,这个原则和使用普通函数一样(这个错误对于新手来说真的很隐蔽而易犯!)

使用构造函数

C++有两种使用构造函数的方式:

int main(void){
	//第一种,通过显式调用来使用构造函数
	Stock food=Stock(42);
	//第二种,隐式调用构造函数
	Stock food2(42);//和上面的第一种调用等价
	//注意,如果想隐式调用默认构造函数,不能加圆括号
	Stock food3;//隐式调用默认构造函数
	return 0;
}

注意,第二种调用方法是构造函数独有的,其他方法不能用这种方式。
构造函数也可以在赋值时使用:

int main(void){
	//利用构造函数进行初始化
	Stock food=Stock(42);
	//利用构造函数进行赋值
	food=Stock(42);
}

析构函数

析构函数比构造函数简单的多,它负责告诉编译器这个对象已经使用完毕,可以被回收。唯一值得一提的是,构造函数也可以在函数体中进行一些操作。

class Stock{
	int i;
	~Stock()//虽然要对所有属性变量进行回收,但函数体中不应有对属性变量的删除操作,编译器会自动回收
	{
		cout<<"this stock is destroy!"//可以进行打印
		cout<<i;//可以使用属性变量
	}
}

析构函数特点和构造函数相同,它的名字是类名前加一个~。
在代码中,程序员不显式调用析构函数,什么时候调用析构函数由编译器自己决定。

列表初始化

这实际上是C++11中引入的另一种隐式调用构造函数的方式。尽管方便,但笔者并不习惯使用,只能说仁者见仁吧。

int main(void)
{
	//隐式调用带参数的构造函数,注意要使用大括号
	Stock hot_tip={42};
	//隐式调用默认构造函数
	Stock hot_tip1{};
}

const成员函数

当一个函数已经被程序员确认不会修改调用它的对象时,应该把它声明为const成员函数。当一个函数被声明为const成员函数时,编译器将知道这个函数不会修改对象,这将提升代码的可读性并规避一些令人迷惑的错误。

this指针

this指针指向调用这个指针的对象本身,函数传入另一个对象时,这个指针会派上用场:

class Stock{
	int i;
	Stock larger(Stock& s)
	{
		if(i>=s.i)return s;//第一个i是调用这个函数的对象的属性i,因此可以写成this->i
		else 
			return *this;//this是指向对象的指针,因此*this就是这个对象本身
	}
}

对象数组

和默认类型一样,对象也可以以数组的形式同时声明多个:

class Stock{
	int i;
	Stock();//默认构造函数
	Stock(int s);//带参数的构造函数
	}
int main(void)
{
	int a[3]={3,2,1}这是int类型声明数组的方式,Stock对象数组大同小异
	Stock s1[3]={Stock(),//第一个对象使用默认构造函数
	Stock(3),//第二个对象使用带参数构造函数
	Stock(),//第三个对象使用默认构造函数
	};
}

对象数组进行初始化时,首先使用默认构造函数创建数组元素,然后再用大括号中的构造函数创建临时对象,最后将临时对象复制进数组元素中。

类作用域

在C++中,类的成员作用域都为该类,在类外使用这个类的成员时,需要加上直接成员运算符(.),间接成员运算符(->)或作用域解析运算符(::):

class Stock{
	int i;
	Stock();//默认构造函数
	Stock(int s);//带参数的构造函数
	void show();
	}
//下面的函数是show方法的定义
Stock::show(){...};//::为作用域解析运算符
int main(void)
{
	Stock s;
	s.show();//.为直接成员运算符
	Stock* sp=s;
	sp->show();//->为间接成员运算符
}

只需要知道类中的成员在类外使用时不能直接用,要加点什么就可以了。至于应该加什么,代码写多了自然就可以自己辨别。

作用域为类的常量

有些常量由类的所有对象共享,这种常量可以用来表示所有对象都需要共同维护的一个信息。有两种方式声明这种变量,枚举和static关键字:

class Stock{
	enum{Months=12}//使用枚举的方法声明常量
	static const int date=30;//使用static的方法声明常量

类作用域内的枚举

传统的枚举在同一个作用域中会有冲突:

enum egg{small,medium,large};
enum t_shirt{small,medium,large};

这种情况下无法通过编译,但如果使用类作用域的枚举,就可以解决这个问题:

enum class egg{small,medium,large};
enum class t_shirt{small,medium,large};

使用枚举量时要用::运算符:

egg e=egg::small;

但要注意,枚举量并非int类型,不能进行隐式类型转换,但显式类型转换也是允许的:

int i=egg::large;//不能通过编译
int a=(int)egg::large;//可以通过编译

枚举量的底层类型未知,取决于实现,但依然可以使用以下语法指定底层类型(在short,int等整型类型中指定):

enum class : short pizza{small,medium,large};//在class后加:short

请添加图片描述
我是霜_哀,在算法之路上努力前行的一位萌新,感谢你的阅读!如果觉得好的话,可以关注一下,我会在将来带来更多更全面的知识讲解!

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

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

相关文章

代码随想录第46天|139.单词拆分,了解多重背包,背包总结

139.单词拆分 动规五部曲 1.确定valid数组以及下标的含义 valid[i] : 字符串长度为i的话&#xff0c;valid[i]为true&#xff0c;表示可以拆分为一个或多个在字典中出现的单词。 2.valid初始化 valid[0]一定要为true&#xff0c;否则递推下去后面都都是false了 3.递推公式…

TDesign WXS语法

目录 一、输出函数返回值如何获取&#xff1f; 二、WXS语法 三、WXS案例 一、输出函数返回值如何获取&#xff1f; 写在js的方法中 wxml中{{方法名()}}输出&#xff1a; 发现不显示&#xff1f;&#xff1f; 所以不能使用这种方式&#xff01;&#xff01; 二、WXS语法 1.…

idea启动缓慢解决办法

idea启动缓慢解决办法 文章目录 idea启动缓慢解决办法前言一、修改内存大小二、虚拟机运行大小三、插件禁用1、安卓相关2、构建工具3、Code Coverage 代码覆盖率4、数据库5、部署工具6、html和xml7、ide settings8、JavaScript框架和工具9、jvm框架10、Keymap快捷键映射11、kot…

c语言练习43:深入理解strcmp

深入理解strcmp strcmp的主要功能是用来比较两个字符串 模拟实现strcmp 比较两个字符串对应位置上的大小 按字典序进行比较 例如&#xff1a; 输入&#xff1a;abc abc 输出&#xff1a;0 输入&#xff1a;abc ab 输出&#xff1a;>0的数 输入&#xff1a;ab abc …

BUUCTF ciscn_2019_n_1 1

分析 使用file命令查看文件信息 使用IDA64打开文件 进入func函数 如果 v2 等于 11.28125 就可以拿到flag 可以看到v1有栈溢出&#xff0c;并且v1在v2的上面&#xff0c;可以通过溢出v2来覆盖v1的值从而获取flag 首先v1是浮点数 11.28125 的二进制是 0x413480 exp from…

【FPGA零基础学习之旅#13】串口发送模块设计与验证

&#x1f389;欢迎来到FPGA专栏~串口发送模块 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;FPGA学习之旅 文章作者技术和水平有限&#xff0c;如果文中出现错误&#xff0c;希望大家能指正&…

Redis 十大核心数据类型解析

一、Redis 简述 redis是一个开源的使用C语言编写的一个kv存储系统&#xff0c;是一个速度非常快的非关系远程内存数据库。它支持包括String、List、Set、Zset、hash五种数据结构。 除此之外&#xff0c;通过复制、持久化和客户端分片等特性&#xff0c;用户可以很方便地将red…

基于Yolov8的NEU-DET钢材表面缺陷检测,优化组合新颖程度较高:CVPR2023 PConv和BiLevelRoutingAttention,涨点明显

1.钢铁缺陷数据集介绍 NEU-DET钢材表面缺陷共有六大类,分别为:crazing,inclusion,patches,pitted_surface,rolled-in_scale,scratches 每个类别分布为: 2.基于yolov8的训练 原始网络如下: map@0.5为0.733

博客系统(升级(Spring))(三)登录功能,注册功能,注销功能

博客系统 (三&#xff09; 博客系统登录用户前端后端数据查询&#xff08;在mapper上添加mapper接口&#xff09; 注册用户前端后端插入数据 注销 博客系统 博客系统是干什么的&#xff1f; CSDN就是一个典型的博客系统。而我在这里就是通过模拟实现一个博客系统&#xff0c;这…

Spring Boot 中使用 Poi-tl 渲染数据并生成 Word 文档

本文 Demo 已收录到 demo-for-all-in-java 项目中&#xff0c;欢迎大家 star 支持&#xff01;后续将持续更新&#xff01; 前言 产品经理急冲冲地走了过来。「现在需要将按这些数据生成一个 Word 报告文档&#xff0c;你来安排下」 项目中有这么一个需求&#xff0c;需要将用户…

Linux平台如何实现采集音视频数据并注入轻量级RTSP服务?

技术背景 好多开发者&#xff0c;问我们最多的问题是&#xff0c;为什么要设计轻量级RTSP服务&#xff1f;轻量级RTSP服务&#xff0c;和RTSP服务有什么区别&#xff1f; 针对这个问题&#xff0c;我们的回答是&#xff1a;轻量级RTSP服务解决的核心痛点是避免用户或者开发者…

59、SpringBoot 自定义JSON的序列化器和反序列化器

Serialization(序列化)&#xff1a; 将java对象以一连串的字节码保存在磁盘文件中的过程&#xff0c;也可以说是保存java对象状态的过程。序列化可以将数据永久保存在磁盘上(通常保存在文件中)。 deserialization(反序列化)&#xff1a; 将保存在磁盘文件中的java字节码重新转…

关于µC/OS-III 多任务的基本理解

关于C/OS-III 多任务的基本理解 任务和任务管理是 RTOS 的核心&#xff0c;且大多数项目使用 RTOS 的目的就是为了使用 RTOS 的多任务管理能力。 C/OS-III作为经典的RTOS&#xff0c;了解并学习其任务管理机制&#xff0c;是非常有必要的。 文章目录 关于C/OS-III 多任务的基本…

进阶C语言-指针的进阶(中)

指针的进阶 &#x1f4d6;5.函数指针&#x1f4d6;6.函数指针数组&#x1f4d6;7.指向函数指针数组的指针&#x1f4d6;8.回调函数 &#x1f4d6;5.函数指针 数组指针 - 指向数组的指针 - 存放的是数组的地址 - &数组名就是数组的地址。 函数指针 - 指向函数的指针 - 存放的…

【Java】session的工作原理

文章目录 一、session的概念及特点session概念session主要有以下的这些特点 二、为什么要使用session三、session的工作原理四、session的生命周期Session何时生效Session何时失效 五、session的性能瓶颈六、session实现登录状态的控制 一、session的概念及特点 session概念 …

无涯教程-JavaScript - COUPDAYSNC函数

描述 COUPDAYSNC函数返回从结算日期到下一个息票日期的天数。 语法 COUPDAYSNC (settlement, maturity, frequency, [basis])争论 Argument描述Required/OptionalSettlement 证券的结算日期。 证券结算日期是指在发行日期之后将证券交易给买方的日期。 RequiredMaturity 证…

基于第二代 ChatGLM2-6B P-Tuning v2 微调训练医疗问答任务

今天是教师节&#xff0c;恭祝全体老师们节日快乐&#xff01;&#x1f60a; 一、ChatGLM2-6B 在本专栏前面文章中实验了使用 ChatYuan-large-v2 Freeze 微调训练医疗问答任务&#xff0c;训练后效果整体还可以&#xff0c;这篇文章继续探索使用最近比较火的 ChatGLM 官方推出…

docker镜像详解

目录 什么是docker镜像镜像相关命令docker pulldocker imagesdocker searchdocker rmi导出 / 导入镜像 镜像分层镜像摘要镜像摘要的作用分发散列值 什么是docker镜像 Docker镜像是Docker容器的基础组件&#xff0c;它包含了运行一个应用程序所需的一切&#xff0c;包括代码、运…

Sharding-Jdbc(2):Sharding-Jdbc入门案例

1 前置条件 搭建读写分离的数据库环境,搭建方法如下文,目标数据库test Mysql性能优化(5):主从同步原理与实现_mysql主从配置优化_不死鸟.亚历山大.狼崽子的博客-CSDN博客 2 新建maven项目 3 pom引入依赖 <?xml version="1.0" encoding="UTF-8"…

《protobuf》基础语法2

文章目录 枚举类型ANY 类型oneof 类型map 类型改进通讯录实例 枚举类型 protobuf里有枚举类型&#xff0c;定义如下 enum PhoneType {string home_addr 0;string work_addr 1; }同message一样&#xff0c;可分为 嵌套定义&#xff0c;文件内定义&#xff0c;文件外定义。不…