类与对象(一)

目录

一、面向过程和面向对象

什么是面向过程?

什么是面向对象?

炒鸡蛋比方理解

面向过程

面向对象

二、类的概念

类到底是个啥,咋来的呢?

听我扯一下

引用

1.可以在其中定义函数

2.结构体名称可以做类型

 定义

注意

 举例

访问限定符

public

 private

 protected

封装

概念

c中问题

c++中解决

三、类的作用域

概念

四、类的实例化

概念

特征

五、计算类对象的大小

存储方式猜想

三种情况

类中既有成员变量,又有成员函数

类中仅有成员函数

类中什么都没有---空类

内存对齐

六、this指针

定义一个日期类

this指针解决上述疑惑

this指针特性

this例题

1.

 2.


一、面向过程和面向对象

什么是面向过程?

要完成一件事,关注的是过程,分析出求解问题的步骤,一步一步按照顺序完成,通过函数调用逐步解决问题。

什么是面向对象?

完成一件事,关注的是对象,将一件事情拆分成不同的对象,在对象中完成其该有的功能,靠对象之间的交互完成。

炒鸡蛋比方理解

面向过程

1.取出鸡蛋、2.敲开鸡蛋、3.将鸡蛋倒进碗里、4.筷子搅拌均匀、5.起锅、6.放油、7.点火、8.等待一定的时间后(时间不用太长,要不然把握不住),将鸡蛋倒入锅中、9.炸至金黄、10.闻到香味、11.出锅放到盘子里、12.撒点盐,开动。
 

按照上述过程,一步步实现,这就是面向过程。

面向对象

炒鸡蛋可分为中有哪些对象?

本人、食物(鸡蛋,盐,油)、餐具(碗、筷子、盘子,锅 )

将炒鸡蛋所需的东西,按照不同的性质分成不同的类,创建不同的对象,在对象中进行实现,最后通过对象的交互,完成炒鸡蛋。

通过各个对象间的相互交互:

本人和鸡蛋交互:完成打碎鸡蛋操作

本人和锅交互:完成起锅、出锅操作

……………

这样就可以实现各个功能,完成炒鸡蛋。

二、类的概念

类到底是个啥,咋来的呢?

听我扯一下

我们在炒鸡蛋中,食物餐具就是两个类,类包含了有相同共性的不同成员。

因此我们首先想到的是:C语言中的结构体! 

c++中出现了类,要实现各个功能,就必须做到类间的交互,功能的实现我们是用函数来实现的

因此得出结论:c++中出现的类,跟我们了解到的结构体和函数有关。

引用

在c++中,是支持C语言中的结构体的;

并且对结构体做了优化,升级成了类

1.可以在其中定义函数

2.结构体名称可以做类型

例如:

在c中定义一个结构体

 在c++中定义结构体

 定义

 但是一般为了区分结构体和类,c++中,写类一般会将 struct 替换为 class

class className
{

    // 类体:由成员函数和成员变量组成

}; // 注意后面的分号

注意

1.成员变量名,前面或后面一般会有一些区别符号:

_ 或者字母等等,目的是为了区分

2.成员变量可以定义在成员函数下方,并且常定义在下方,因为类是一个整体,不会存在找不到的问题

类就是结构体升级来的类型,而对象类这个类型定义的变量。

升级的结构体类型 = 类

结构体变量 = 对象

 举例

#include <iostream>
using namespace std;

struct Food
{
	//成员函数
	void Init(const char* name, int num)
	{
		strcpy(_name, name);
		_num = num;
	}
	void Print()
	{
		cout << _name << " " << _num << endl;
	}

	//成员变量
	char _name[10];
	int _num;
};

int main()
{
	Food egg;
	egg.Init("鸡蛋",2);
	egg.Print();
	return 0;
}

可以将struct 替换为class

会发现出现访问问题!! 

 那就是访问权限的问题!!

class不加访问限定符,默认的访问权限时私有的

struct不加访问限定符,默认的访问权限是公有的

-->访问限定符

访问限定符

public

public 修饰的成员在类外可以直接被访问

要解决上一步不可访问的问题:

加上 public:即可,如下:

 private

private 修饰的成员在类外不能直接被访问

若给结构体加上private:如下:

 protected

protected和private修饰的成员在类外不能直接被访问

当然是有区别的,现阶段我们只需要记住这两个效果相似就好。

封装

封装是c++面向对象的三大特性封装、继承、多态)之一

概念

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

c中问题

数据的定义和操作数据的方法是分开的,就比如栈。定义栈的时候,数据是在栈的定义中,而初始化,进栈,栈顶元素这些方法是在定义外实现的。

这样的布局往往会造成操作的不规范,比如想要得到栈顶元素

规范操作就直接使用我们的函数就可以,但是有不规范的人可对数据进行直接访问,往往会产生误用,如下:

c++中解决

c++如何解决上述问题?

用到封装,可以强制规范操作。

将数据和操作数据的方法放在类中,并且用访问限定符进行修饰,防止对数据的直接操作。

一般情况下,类中,数据成员都是私有的,想要被访问的函数是公有的,不想被访问的是私有或者保护。

三、类的作用域

概念

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员,需要使用 :: 作用域解析符指明成员属于哪个类域。

和之前学到的命名空间一样,命名空间也是一个作用域。

在类中,一般存放的是数据和函数的声明,函数在类外定义。

也可以在类中定义,要注意:

在类中定义的函数默认是内联函数,因此简短的函数可以在类中直接定义。

那么类就应在头文件中:

函数实现单独放在一个.cpp中:

函数应在类域中,函数名前应指定作用域:

这样相当于函数包括函数下面的参数都是类中直接使用的,与访问限定符没有关系。

无论是哪一个限定符修饰的成员,在类中都可以被直接调用。

四、类的实例化

概念

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

特征

定义出一个类并没有分配实际的内存空间来存储它
一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
类相当于对象的模板

五、计算类对象的大小

类中既可以有成员变量,又可以有成员函数,如何计算一个类的大小?

存储方式猜想

对象中包含类的各个成员,函数和数据都占内存

 这里,我们创建两个对象,进行相同函数成员的调用:

说明了类创建的对象函数是共用的,数据不可能共用,因为每个对象的数据都是不同的。

若按照猜想来进行存储,类创建多个对象时,每个对象中都会保存一份代码,相同代码保存多次,浪费空间。

因此猜想错误

类的对象中只保存成员变量,成员函数存放在公共的代码段

那么类对象的大小计算就跟结构体差不多了,要注意内存对齐。

三种情况

类中既有成员变量,又有成员函数

class A1 {
public:
	void f1(){}
private:
	int _a;
};

只存储成员变量,按照计算结构体大小的方法,注意内存对齐

类中仅有成员函数

class A2 {
public:
	void f2() {}
};

对象中不存储成员函数,但是为了保证存在这个对象,会给对象开辟一个字节的空间

类中什么都没有---空类

class A3
{};

和仅有成员一样,不存储任何东西,为了说明类创建的对象存在,会相应的给予一个字节的空间

内存对齐

链接在这:自定义类型详解_i跑跑的博客-优快云博客

六、this指针

定义一个日期类

//日期类
class Date
{
public:
	void Time(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()
{
	Date d1, d2;
	d1.Time(2001, 5, 15);
	d2.Time(2022, 10, 30);
	d1.Print();
	d2.Print();
	return 0;
}

this指针解决上述疑惑

C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

编译器处理函数成员:

this指针特性

1. this指针的类型:类类型* const

因为是const修饰,this指针不能更改

但是被this指针修饰的内容可以更改

 
2. 只能在“成员函数”的内部使用


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


4. this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递

 指针一般存放在栈中,有些编译器优化后会存放在寄存器中,更加方便高效。

this例题

1.

class A
{
public:
	void Show()
	{
		cout << "Show()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	p->Show();
}

 2.

class A
{
public:
	void Show()
	{
		cout << _a << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	p->Show();
}


类与对象的个人理解可能存在问题,有些牵强,有问题的地方希望伙伴们私信或在讨论区帮忙指正呀,学习笔记的记录,正确是前提,希望我们都能有所收获,共同进步!!

评论 35
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今年依旧去年春

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值