【C++打怪之路Lv3】-- 类和对象(上)

🌈 个人主页:白子寰

🔥 分类专栏:C++打怪之路,python从入门到精通,数据结构,C语言,C语言题集 👈 希望得到您的订阅和支持~

💡 坚持创作博文(平均质量分82+),分享更多关于深度学习、C/C++,python领域的优质内容!(希望得到您的关注~)

目录

面向对象和面向过程的认识

类的引入(以下以Stack为例)

类的介绍

类的第一种定义方法

类的第二种定义方法:类的作用域

成员变量命名规则

建议①

建议②

类的访问限定符

访问限定符的介绍

封装

类的实例化

概念

理解类的实例化(含图片和代码)

类对象模型

计算类对象大小

结构体内存对齐

this指针

this指针的引入

this指针的特性

C语言和C++实现Stack的对比

C语言

C++


面向对象和面向过程的认识

C语言是面向过程 的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。

而C++是基于面向对象 的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。

那什么是过程?什么是对象呢?

我们在生活中举例子:比如我要去烧一壶开水

对象:我,热水壶,水,排插/插座,热水壶托盘

过程:把水接到水壶里 --> 关闭水壶盖 --> 把热水壶放到托盘中 --> 连接好插排/插座 --> 按下热水壶开关 --> 静等几分钟 -->一壶水烧开了



类的引入(以下以Stack为例)

在C语言中,我们学过结构体,但在C语言的结构体当中,只能由成员变量组成,回顾一下怎么用C语言实现(Stack)栈的呢?


然而在C++ 当中,结构体里不仅可以定义成员变量,还可以定义成员函数,那就是"类"


类的介绍

在C++当中,喜欢把struct写成class(类),什么是类?

cpp 复制代码
class ClassName
{
    //由 成员变量 和 成员函数 来组成
};

注:1、class和struct相似, 2、ClassName是类的名称,

3、名称后需跟中括号{},4、右中括号后还有分号 ( ; )


那么在C++当中关于栈的类是怎么定义的呢?

类的第一种定义方法

在class(类)中声明和定义成员变量和成员函数(可以在class中具体实现成员函数)

注:(成员函数如果放在类体中,编译器可能会当成内联函数处理)

(关于访问权限我们在后续中会讲到,这里先做铺垫)


类的第二种定义方法:类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。

在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域。

在class(类)中定义成员变量和定义成员函数,

在.cpp文件中声明成员函数 (也就是通过类和作用域限定符指定实现Stack类中的某个函数)


成员变量命名规则

建议①

成员变量用**_year** 表示

建议②

成员变量用 前缀(m_year) 或者 **后缀(例如:year_m)**来表示


类的访问限定符

访问限定符的介绍

C++实现封装(文章下面会讲到)的方式:

用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。

访问限定符包括:public(公有),protected(保护),private(私有)

注: 1、public修饰的成员在类外是直接可以访问的

2、private修饰的成员在类外不能直接被访问(protect和private是类似的)

3、访问权限作用域从访问权限开始到下一个访问权限出现结束

4、 如访问没有限定符,那就到 } 结束

5、class默认访问权限是private,struct默认访问权限是public(struct兼容C语言)



封装

面向对象的三大特性:封装、继承、多态

在类和对象阶段,主要是研究类的封装特性,那什么是封装呢?

封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来 和对象进行交互。

封装本质上是一种管理,让用户更方便使用类

就像上面说的 面向对象和面向过程的认识 一样

烧一壶开水,我们只需关心把水装进水壶,再按下按钮就可以了

并不关心开水是怎么烧开的,它的内部用什么装置和线路组成的(封装)

用户 只需要与厂家提供的按钮,热水壶等显而易见直接实现的外部装置之间进行交互

在C++语言中实现封装,

可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用。



类的实例化

概念

用类类型创建对象的过程,称为类的实例化

类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,

定义出一个类并没有分配实际的内存空间来存储它

打个比方:

类实例化出对象就像现实中使用建筑设计图建造出房子,

类就像是设计图 ,只设计出需要什么东西,但是并没有实体的建筑存在

同样类也只是一个设计实例化出的对象才能实际存储数据,占用物理空间

类 和 对象 是 一对多的关系

一个类可以有多个对象,比方类是设计图,对象是通过设计建出来的房子,

一个设计图可以设计建造出多个类似的房子


理解类的实例化(含图片和代码)

举例:Data日期类

cpp 复制代码
class Data
{
public:
	void Init(int yaer, int month, int day)
	{
		m_year = yaer;
		m_month = month;
		m_day = day;
	}

private:
	int m_year; //年
	int m_month;//月
	int m_day;  //日
};

int main()
{
	Data s1;		//定义(实例化)对象
	Data s2;		//定义(实例化)对象
	s1.Init(2024, 4, 25);
	s1.Init(2024, 4, 25);

	Data s3;		//定义(实例化)对象
	Data s4;		//定义(实例化)对象

	s1._yaer++;		//成员变量的权限为private
	s2._yaer++;
	return 0;
}


类对象模型

计算类对象大小

(看下面Data类,类A、B、C)

cpp 复制代码
class Data
{
public:
	void Init(int yaer, int month, int day)
	{
		_year = yaer;
		_month = month;
		_day = day;
	}

private:
	int _year;
	int _month;
	int _day;
};

class A
{};

class B
{
private:
	int a;
	char b;
};

class C
{
public:
	void D(){}
};

int main()
{
	Data d1;

	cout << sizeof(d1) << endl;
	cout << sizeof(A) << endl;
	cout << sizeof(B) << endl;
	cout << sizeof(C) << endl;
}

怎么计算类对象的大小呢?(Data类,类A、B、C)它们的大小分别为多少?

一个类的大小,实际就是该类中"成员变量"之和

当然要注意内存对齐注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象。

控制台输出显示


结构体内存对齐

详细讲解请看该篇文章:结构体超详细总结(含结构体内存对齐)http://t.csdnimg.cn/YIAAr



this指针

this指针的引入

看一下前面提到的Data(日期类)

cpp 复制代码
class Data
{
public:
	void Init(int yaer, int month, int day)
	{
		_year = yaer;
		_month = month;
		_day = day;
	}

	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Data d1;
	Data d2;

	d1.Init(2024, 4, 27);
	d2.Init(2023, 4, 27);

	d1.Print();
	d2.Print();

	return 0;
}

现有这样一个问题,

当d1调用Init成员函数时,该函数如何知道应该设置d1对象而不是设置d2对象呢?

C++中通过引入this指针解决该问题,

即:C++编译器给每个"非静态的成员函数"增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),

在函数体中所有"成员变量"的操作,都是通过该指针去访问。

只不过所有的操作对用户是透明 的,即用户不需要来传递,编译器自动完成

this指针的特性

1、this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。

2、 只能在**"成员函数"的内部使用**

3、this指针 本质上是"成员函数"的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。

4、this指针是"成员函数"第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传

递,不需要用户传递


d1和d2都调用该成员函数,但结果却不同的原因是:

void Print() 函数再编译器编译是 void Print(Data* const this),有一个隐藏参数this指针

d1调用函数时,是这样子来访问的:

&d1->_year、&d1->_month、&d1->_day,

此时this指针就是d1的指针,&d1是实参,Data* this是形参(局部变量),访问的是d1的对象_year,_monh,_day



C语言和C++实现Stack的对比

C语言

共性

1、每个函数的第一个参数都是Stack*

2、函数中必须要对第一个参数检测,因为该参数可能会为NULL函数中都是通过Stack*参数操作栈的

3、调用时必须传递Stack结构体变量的地址

结构体中只能定义存放数据的结构,操作数据的方法不能放在结构体中,即数据和操作数据的方式是分离开的,而且实现上相当复杂一点,涉及到大量指针操作,稍不注意可能就会出错。


C++

C++中通过类 可以将数据 以及 操作数据的方法进行完美结合

通过访问权限可以控制那些方法在类外可以被调用,即封装,在使用时就像使用自己的成员一样,更符合人类对一件事物的认知。

而且每个方法不需要传递Stack*的参数了,编译器编译之后该参数会自动还原,

即C++中 Stack * 参数是编译器维护的,C语言中需用用户自己维护。



***********************************************************分割线*****************************************************************************
完结!!!
感谢浏览和阅读。

等等等等一下,分享最近喜欢的一句话:

"欲买桂花同载酒,终不似,少年游"。

我是白子寰,如果你喜欢我的作品,不妨你留个点赞+关注让我知道你曾来过。
你的点赞和关注是我持续写作的动力!!!

好了划走吧。

相关推荐
sukalot8 分钟前
windows C++-windows C++-使用任务和 XML HTTP 请求进行连接(二)
c++·windows
_.Switch10 分钟前
Python机器学习模型的部署与维护:版本管理、监控与更新策略
开发语言·人工智能·python·算法·机器学习
醉颜凉13 分钟前
银河麒麟桌面操作系统修改默认Shell为Bash
运维·服务器·开发语言·bash·kylin·国产化·银河麒麟操作系统
NiNg_1_23419 分钟前
Vue3 Pinia持久化存储
开发语言·javascript·ecmascript
带带老表学爬虫27 分钟前
java数据类型转换和注释
java·开发语言
qianbo_insist30 分钟前
simple c++ 无锁队列
开发语言·c++
zengy531 分钟前
Effective C++中文版学习记录(三)
数据结构·c++·学习·stl
BigYe程普41 分钟前
我开发了一个出海全栈SaaS工具,还写了一套全栈开发教程
开发语言·前端·chrome·chatgpt·reactjs·个人开发
彭于晏68942 分钟前
Android广播
android·java·开发语言
弱冠少年1 小时前
websockets库使用(基于Python)
开发语言·python·numpy