【C++类】

目录

  • 前言
  • 一、类的定义
  • 二、类的访问限定符及封装
    • 2.1访问限定符
    • 2.2封装
  • 三、类的大小
    • 3.1为什么需要内存对齐
    • 3.2为什么成员函数不占用类的内存?
    • 3.3为什么空类的大小是1个字节?
  • 四、this指针
    • 4.1this指针的引入
    • 4.2this指针的特性
  • 五、类的6个默认成员函数
    • 5.1构造函数
      • 5.1.1构造函数的特性
    • 5.2析构函数
    • 5.3拷贝构造函数
    • 5.4复制运算符重载
    • 5.5const成员函数
    • 5.6 取地址及const取地址操作符重载

前言

今天是少年正式认识"对象"的第一天,虽然此"对象"非彼对象,但是少年也想好好的与你认识认识,所以少年在这里先跟你打个招呼。
blog.csdnimg.cn/6c5d5eed216445669dfadb9442adadb8.png)
我们都知道豹子、老虎、猫…都是猫科动物。这里我们用猫科动物来作为这些动物的,而豹子、老虎、猫是这个类下的具体动物即对象。在生活中有了类与对象的概念我们就可以很简单描述一个复杂的事物。比如:王者荣耀是一个我方英雄与敌方英雄的塔防游戏。英雄是类,塔也是类,用了两个类就简单的描述了几百万人玩的游戏。试想一下假如没有类的概念你该怎么描述呢?
而在C++中为了更好的"表达"也引入了对象的概念(祖师爷666)。

一、类的定义

C++中使用关键字 class 来定义类, 其基本形式如下:

class className
{
 // 类体:由成员函数和成员变量组成
 
}; // 一定要注意后面的分号

class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。
类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。
类的两种定义方式:

  1. 声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
class Hero
{
public:
	//英雄的1技能
	int func1()
	{
		return 0;
	}
	//英雄的2技能
	int func2()
	{
		return 0;
	}
	//英雄的3技能
	int func3()
	{
		return 0;
	}
	//英雄的4技能
	int func4()
	{
		return 0;
	}
private:
	//英雄名字
	char name[20];
	//英雄血条
	int Hp;
};

2.类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::
Tower.h文件

#pragma once
class Tower
{
public:
	//塔的攻击功能
	int Attack();
private:
	//塔的名字
	char name[20];
	//塔的血量
	int Hp;
	//塔的伤害值
	int DamageValue;
};

Tower.cpp文件

#include"Tower.h"
int Tower::Attack()
{
	return 0;
}

一般情况下,更期望采用第二种方式。好处现在可能不太明显,后面代码量上去后可能自己就有了体会,特别是还加了继承与多态。

二、类的访问限定符及封装

2.1访问限定符

在这里插入图片描述
【访问限定符说明】

  • public修饰的成员在类外可以直接被访问
  • protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
  • 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
  • 如果后面没有访问限定符,作用域就到 } 即类结束。
  • class的默认访问权限为private,struct为public(因为struct要兼容C)

2.2封装

C++中面向对象的特性有三:封装、继承、多态。学到这里代表少年面向对象的思想刚刚开始入门了。
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。假设你是王者荣耀的实现团队的leader,你希望你的团队写出在英雄放技能时可以修改英雄固定的属性值的代码吗?可能的不行的。
通过需要访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用就是封装。

三、类的大小

前面在学习C语言的时候知道了结构体大小的计算,这里面主要涉及到内存对齐,同样类的大小计算也要涉及到内存对齐。比如:
在这里插入图片描述
那么为什么要有内存对齐规则呢?上次在C语言里没有细说,这次借助C++的类在这里展开一下。

3.1为什么需要内存对齐

  • 首先不是所有的硬件平台都能访问任意地址上的数据。
  • 其次某些硬件平台只能只在某些地址访问某些特定类型的数据,否则抛出硬件异常,及遇到未对齐的边界直接就不进行读取数据了。
  • 最后为了代码的可移植性,和提升CPU访问内存的效率,所以结构体一定要内存对齐。本质:空间换区时间的做法。
    在这里插入图片描述
    cpu的内存由于硬件的原因是一块一块的,块的大小可能是2字节、4字节、8字节取决于硬件,因此cpu在读取内存时是一块一块的读取的。不可以随机访问某一个地址,但是可以随机访问某个倍数倍的地址。比如:
    在这里插入图片描述
    最后对比一下对齐与不对齐的读取效率。如图:
    在这里插入图片描述

3.2为什么成员函数不占用类的内存?

话不多说直接上图:
在这里插入图片描述
在这里插入图片描述
通过2张图可以发现类的大小是真的与类内的成员函数无关。但是这是为什么呢?这主要与类的存储方式有关。如图:
在这里插入图片描述
成员函数不像成员属性那么特殊(每个对象的属性是独一无二的),成员函数就像是对象的方法你想用直接去公共代码区调用就好,不用每个对象都"带着"这样浪费空间。

3.3为什么空类的大小是1个字节?

直接上图:
在这里插入图片描述
按道理应该是0呀?为什么是1呢?假设是0字节大小,即不在内存上存储。那么少年问你,对一个类取地址这个操作犯毛病吗?应该是合理的哟,但是它都不在内存上了它的地址是多少呢?所以为了出现这么的情况,编译器给了一个字节的空间来存储这个类,来证明这个类存在过。
在这里插入图片描述

四、this指针

4.1this指针的引入

思考一下下面的代码为什么会是这样的打印结果呢?
在这里插入图片描述
根据上面的分析d1与d2都应该是调用的同一个函数(下图可以证明),而且函数貌似也没有传参呀。为什么打印结果会不同呢?
在这里插入图片描述
其原因是:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
在这里插入图片描述
注:this不能在形参和实参显示传递,但是可以在函数内部使用且this指向不能改。所以严格意义上是这样的。
在这里插入图片描述

4.2this指针的特性

问题1:this指针存放在哪?

由上图可知this指针是个形参,所以存放在栈区。

问题2:this指针可以为空吗?回答这个问题前先做这样一道题:
在这里插入图片描述
this指针可以为空,但是注意不要在成员函数内对它解引用。
学到这里我们也就可以理解为什么A::Print();这样写法不行。因为编译器不知道传个什么东西给this指针。

五、类的6个默认成员函数

如果一个类中什么成员都没有,简称为空类。
空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。
在这里插入图片描述

5.1构造函数

5.1.1构造函数的特性

构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次。
其特征如下:

  1. 函数名与类名相同。
  2. 无返回值。
  3. 对象实例化时编译器自动调用对应的构造函数。
  4. 构造函数可以重载。比如:
#include<iostream>
using namespace std;
class Data
{
public:
	Data()
	{ }
	 Data(int year, int month, int day)
	{
		Year = year;
		Month = month;
		Day = day;
	}
	void Print()
	{
		cout << Year << "-" << Month << "-" << Day << endl;
	}
private:
	int Year;
	int Month;
	int Day;
};
int main()
{
	Data d1;//调用的是无参构造函数
	Data d2(2022,12,12);//调用的是有参构造函数
	d1.Print();
	d2.Print();
	return 0;
}
  1. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
  2. 关于编译器生成的默认成员函数,很多童鞋会有疑惑:不实现构造函数的情况下,编译器会生成默认的构造函数。但是看起来默认构造函数又没什么用?d对象调用了编译器生成的默认构造函数,但是d对象_year/_month/_day,依旧是随机值。也就说在这里编译器生成的默认构造函数并没有什么用??
    解答:C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如:int/char…,自定义类型就是我们使用class/struct/union等自己定义的类型,看看下面的程序,就会发现编译器生成默认的构造函数会对自定类型成员_t调用的它的默认成员函数。
#include<iostream>
using namespace std;
class Time
{
public:
	Time()
	{
		cout << "Time()" << endl;
		_hour = 0;
		_minute = 0;
		_second = 0;
	}
private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
private:
	// 基本类型(内置类型)
	int _year;
	int _month;
	int _day;
	// 自定义类型
	Time _t;
};
int main()
{
	Date d;
	return 0;
}

注意:C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在类中声明时可以给默认值。

#include<iostream>
using namespace std;
class Time
{
public:
	Time()
	{
		cout << "Time()" << endl;
		_hour = 0;
		_minute = 0;
		_second = 0;
	}
private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
private:
	// 基本类型(内置类型)
	int _year=2022;
	int _month=12;
	int _day=12;
	// 自定义类型
	Time _t;
};
int main()
{
	Date d;
	return 0;
}
  1. 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。

5.2析构函数

5.3拷贝构造函数

5.4复制运算符重载

5.5const成员函数

5.6 取地址及const取地址操作符重载

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

飞书接入ChatGPT - 将ChatGPT集成到飞书机器人,直接拉满效率 【飞书ChatGPT机器人】

文章目录 前言环境列表视频教程1.飞书设置2.克隆feishu-chatgpt项目3.配置config.yaml文件4.运行feishu-chatgpt项目5.安装cpolar内网穿透6.固定公网地址7.机器人权限配置8.创建版本9.创建测试企业10. 机器人测试 前言 在飞书中创建chatGPT机器人并且对话,在下面操作步骤中,使…

6.4 一阶方程组与高阶方程的数值解法

学习目标&#xff1a; 学习一阶方程组与高阶方程的数值解法的目标可以分为以下几个方面&#xff1a; 掌握一阶方程组和高阶方程的基本概念和求解方法&#xff1b;理解数值解法的概念和原理&#xff0c;了解常见的数值解法&#xff1b;掌握欧拉方法、改进欧拉方法和龙格-库塔方…

深入探讨Linux驱动开发:Linux设备树

文章目录 一、设备树介绍二、设备树框架1.设备树框架2.节点基本格式3.节点部分属性简介 总结 一、设备树介绍 设备树&#xff08;Device Tree&#xff0c;简称 DT&#xff09;是一种在嵌入式系统中描述硬件设备的一种数据结构和编程语言。它用于将硬件设备的配置信息以树形结构…

Springboot 中快速完成文件上传,整合多平台神器

哈喽&#xff0c;大家好~ 又是做好人好事的一天&#xff0c;有个小可爱私下问我有没有好用的springboot文件上传工具&#xff0c;这不巧了嘛&#xff0c;正好我私藏了一个好东西&#xff0c;顺便给小伙伴们也分享一下&#xff0c;demo地址放在文末了。 文件上传在平常不过的一…

最新,有8本SCIE期刊被剔除,4月SCIESSCI期刊目录更新(附最新目录下载)

2023年4月18日&#xff0c;科睿唯安更新了WOS期刊目录&#xff0c;继上次3月WOS期刊目录更新大变动之后&#xff0c;此次4月更新又有8本SCIE期刊发生变动&#xff0c;其中有4本期刊被剔出SCIE数据库&#xff0c;4本期刊更改了名称和ISSN号。更新后的最新SCIE期刊目录共有9505本…

Flask 与 Django 先学哪个呢

本文把 Flask 和 Django 做一个比对&#xff0c;因为我对这两个 Python Web 框架都有实际的开发经验。希望我可以帮助您选择学习哪个框架&#xff0c;因为学习一个框架可能会非常耗时 —— 当然也很有趣&#xff01; 相似之处 让我们从相似之处开始。 No. 1 Flask 和 Djang…

【ctfshow】命令执行->web29-web44

前言 半夜网抑云听歌听emo了 z 刷会儿题不然睡不着了呜呜呜 红中(hong_zh0) CSDN内容合伙人、2023年新星计划web安全方向导师、 华为MindSpore截至目前最年轻的优秀开发者、IK&N战队队长、 吉林师范大学网安大一的一名普通学生、搞网安论文拿了回大挑校二、 阿里云专家博…

数据结构复习题(包含答案)

第一章 概论 一、选择题 1、研究数据结构就是研究&#xff08; D &#xff09;。 A. 数据的逻辑结构 B. 数据的存储结构 C. 数据的逻辑结构和存储结构 D. 数据的逻辑结构、存储结构及其基本操作 2、算法分析的两个主要方面是&#xff08; A …

【小技巧】word文档编辑技巧(一)

文章目录 一、显示显示导航显示所有字符 二、格式格式-三级目录格式-文本格式-图格式-表格式-公式格式-参考文献 三、小技巧交叉引用连续交叉引用表/图目录等自动更新分节符设置页眉/页码word转pdf带导航 一、显示 显示导航 开启导航&#xff1a;视图->显示框->导航窗格…

【Python从入门到进阶】16、文件的打开和关闭

接上篇《15、函数的定义和使用》 上一篇我们学习了Python中函数的定义和使用&#xff0c;包括函数的参数、返回值、局部变量和全景变量等操作。从本篇开始我们来开始学习Python对文件的一些操作&#xff0c;本篇我们主要讲解如何使用Python打开和关闭文件。 一、打开/创建文件…

【SVN】windows SVN安装使用教程(服务器4.3.4版本/客户端1.11.0版本)

介绍 这里是小编成长之路的历程&#xff0c;也是小编的学习之路。希望和各位大佬们一起成长&#xff01; 以下为小编最喜欢的两句话&#xff1a; 要有最朴素的生活和最遥远的梦想&#xff0c;即使明天天寒地冻&#xff0c;山高水远&#xff0c;路远马亡。 一个人为什么要努力&a…

【设计模式】Java 的三种代理模式

文章目录 一、前言二、正文1、静态代理2、动态代理3、Cglib代理Spring中AOP使用代理 三、总结 一、前言 代理(Proxy)模式是一种结构型设计模式&#xff0c;提供了对目标对象另外的访问方式&#xff1b;即通过代理对象访问目标对象。 这样做的好处是&#xff1a;可以在目标对…

activeMQ持久化报错的问题

activeMQ持久化&#xff0c;启动activeMQ报错&#xff0c; INFO | Using Persistence Adapter: JDBCPersistenceAdapter(org.apache.commons.dbcp2.BasicDataSource5148e82a) jvm 1 | WARN | Could not get JDBC connection: Cannot create PoolableConnectionFactory (Commun…

前端学习:HTML头部、布局

目录 HTML头部 一、HTML 元素 二、head标签和header标签的不同 三、HTML 元素 四、HTML 元素 五、HTML 元素 六、 HTML 七、HTML元素 为搜索引擎定义关键词&#xff1a; 为网页定义描述内容&#xff1a; 每60秒刷新当前页面&#xff1a; 八、HTML 九、HTML头部元素…

【故障检测】基于 KPCA 的故障检测【T2 和 Q 统计指数的可视化】(Matlab代码实现)

&#x1f4a5; &#x1f4a5; &#x1f49e; &#x1f49e; 欢迎来到本博客 ❤️ ❤️ &#x1f4a5; &#x1f4a5; &#x1f3c6; 博主优势&#xff1a; &#x1f31e; &#x1f31e; &#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 …

AI语音生成器是下一大安全威胁吗?

ChatGPT一经上市&#xff0c;有关监管人工智能的讨论就开始升温。任何试图遏制这种技术的做法都可能需要国际合作&#xff0c;需要我们在过去几十年来从未见过的合作程度&#xff0c;因此不太可能遏制人工智能。 人工智能是一项功能强大的技术&#xff0c;有望彻底改变我们生活…

Domino自带的JSON校验工具

大家好&#xff0c;才是真的好。 JSON数据在Notes/Domino已经变得非常重要。从Domino 10开始&#xff0c;在LotusScript语言中就加入了对JSON数据处理功能。在管理中&#xff0c;我们知道&#xff0c;从Domino 12版本开始就支持Domino自动化配置&#xff0c;也是使用JSON数据作…

C++ 简介

C 完全支持面向对象的程序设计&#xff0c;包括面向对象开发的四大特性&#xff1a; 封装&#xff08;Encapsulation&#xff09;&#xff1a;封装是将数据和方法组合在一起&#xff0c;对外部隐藏实现细节&#xff0c;只公开对外提供的接口。这样可以提高安全性、可靠性和灵活…

第一个机器学习应用:鸢尾花分类

目录 1. 特征数据与标签数据 2. 训练数据与测试数据 3. 构建模型机器学习模型 4. 预测与评估 4.1 预测 4.2 评估 5. 学习小结 准备&#xff1a;采用Scikit- learn中鸢尾花数据集&#xff0c;完成一个简单的机器学习应用&#xff0c;构建第一个机器学习模型。 已知&…

leetcode 879. Profitable Schemes(有利润的计划)

有几个工程&#xff0c;每个工程需要group[ i ]个人去做&#xff0c;做完了可以得到profit[ i ]的利润。 现有2个限制条件&#xff1a; 人数上限是n, 且参加了一个工程的人不能再参加其他工程。 利润下限minProfit, 至少要获得minProfit的利润。 问有多少种工程的选法&#xff…
最新文章