【C++】踏上C++的学习之旅(六):深入“类和对象“世界,掌握编程的黄金法则(一)
文章目录
- 前言
- 1. "面向过程"和"面向对象"的碰撞
- 1.1 面向过程
- 1.2 面向对象
- 2. "类"的引入
- 3. "类"的定义
- 3.1 🍉语法展示:
- 3.2 "类"的两种定义方式
- 3.3 "类"的命名规则
- 4. 类的访问限定符以及封装
- 4.1 为什么在类中需要访问限定符?
- 4.2 访问限定符
- 4.3 封装
- 5. "类"的作用域
- 6. "类"的实例化(重点理解)
- 7. "类"对象模型
- 7.1 如何计算类对象的大小
- 7.2 类对象的存储方式猜测
- 8. this指针
- 8.1 this指针的引出
- 8.2 this指针的特性
- 8.3 关于this指针的面试题
前言
在本文中我们即将要接触到C++的第一块"硬骨头"——“类和对象”。为什么说"类和对象"是一块一骨头呢?因为里面涉及的语法细节十分的繁杂,不过读者们不必担心,我的"类和对象"这个系列会罗列和讲解各种语法细节,还要对这些地方加以认证,以帮助大家能够感知到这些细节的存在更好的理解"类和对象"的玩法!
另外,本文作为该系列的第一篇文章,会重点讲解从C语言过渡到C++这个时期的"类和对象",以及介绍关于"类和对象"背后的编程思想——“封装”。最后的最后,也是本文会讲解一些"类和对象"的构成和基本规则(再次声明十分重要!),内容精彩,不容错过。
好了,话不多说,让我们开始愉快的学习吧!

1. "面向过程"和"面向对象"的碰撞
1.1 面向过程
我们都知道C语言是面向过程的,关注的是问题求解的步骤或过程。而这些步骤我们都可以用函数一个个进行封装和实现,最后按照逻辑通过函数的调用逐步解决问题。这个就是C语言面向过程的玩法!
可能上面的讲解比较的枯燥,那下面我举一个生活中的例子带着大家好好感受一下什么叫做"面向过程"!
假设现在我们要洗衣服,以"面向过程"思想来解决洗衣服这个问题,我们会这么做:
每一个过程如果我们用C语言来写,都可以用一个函数来表示。相信讲到这里,大家已经对"面向过程"有了一定的感觉了。
1.2 面向对象
那么接下来,我们来聊一聊什么又是"面向对象"?
基于对"面向过程"的理解,有的读者就会说:“这个我知道!如果还拿洗衣服作为例子的话,按照上图来说,这里的"对象"就是"人、衣服、洗衣机和洗衣粉"。如果换做是编程思想的话,我们只需要在这四个对象里面进行对应的代码编写,最后通过这些对象的有机结合能够完成最终的任务!”
没错这个理解是没有问题的!
这里我们就可以对"面向对象"做一个小结,所谓的"面向对象"就是将一件事情拆分成不同对象,靠对象之间的交互完成任务。而 C++是基于面向对象的编程语言,所以这个思想极其重要!
我们讲了这么多,那"类"和"对象"究竟在C++的代码世界中是何种存在?接下来,我就来解开它俩的神秘面纱。

2. "类"的引入
在C语言中,结构体中只能定义变量,在C++中结构体不仅可以定义变量,而且还可以定义函数。
比如我用C语言写一个关于日期的实现,我们这样写的:
//用C语言写的一个关于日期的实现
#include<stdio.h>
typedef struct Date
{int year;int month;int day;
}Date;//对Date结构体进行初始化
void DateInit(Date* d)
{//为了方便演示,这里我就随便初始化了d->year = 1;d->month = 1;d->day = 1;
}void DatePrint(Date* d)
{printf("%d年%d月%d日\n", d->year, d->month, d->day);
}int main()
{Date d1;DateInit(&d1);DatePrint(&d1);return 0;
}
在C++中,将"
struct"升级成了"类",也就是可以在struct中定义函数了!
下面是C++的写法:
struct Date //也可以写成 class Date
{//对Date结构体进行初始化void DateInit(){//为了方便演示,这里我就随便初始化了year = 1;month = 1;day = 1;}void DatePrint(){printf("%d年%d月%d日\n", year, month, day);}int year;int month;int day;
};int main()
{Date d1;d1.DateInit();d1.DatePrint();return 0;
}
对比一发现,C++的写法更加的简洁和优美。但是在C++中更喜欢用class这个关键字来替代struct。
3. "类"的定义
3.1 🍉语法展示:
class className
{//类体:由成员变量和成员函数组成}; //这里有一个分号,一定不要忘记写它
class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。
类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。
3.2 "类"的两种定义方式
类的两种定义方式:
- 声明和定义全部放在类中。需要注意:成员函数如果在类中定义,编译器可能会将它视为内联函数处理

- 类声明放在.h的头文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加入类名
::(目的是指明类域,为编译器的链接工作做准备)

一般情况下,更期望大家能够采用第二种方式。
3.3 "类"的命名规则
关于类中成员变量的命名也是有"说法"的。
请看下面的例子:
// 我们看看这个函数,是不是很僵硬?
class Date
{
public:void Init(int year){// 这里的year到底是成员变量,还是函数形参?year = year;}
private:int year;
};
上面的写法,大大降低了程序的可读性,不推荐大家这样写。
所以我一般建议大家,定义变量名时一定要明确哪个是类中的成员变量,哪个又是成员函数中的变量。解决这个问题的方法就是,以一种特殊的写法来确保类中的成员变量与众不同!
我这里推荐的成员变量命名方式是以下划线为开头,后面跟有意义的名称!
那上面的例子,我们就可以改造成这样:
class Date
{
public:void Init(int year){// 这样的目的就很明确了,就是用year变量去赋值给成员变量_year_year = year;}
private:int _year;
};
当然成员变量名的命名格式不局限于上面的这种,其他方式也是可以的,最终能达到目的就行。
我们也可以这样
class Date
{
public:void Init(int year){// 这样的目的就很明确了,就是用year变量去赋值给成员变量_yearmYear = year;}
private:int mYear;
};
4. 类的访问限定符以及封装
4.1 为什么在类中需要访问限定符?
有些时候,我们期望类中的有些变量是私密的,我不想让你看到,更不想让你访问到。此时我们就可以将成员变量通过访问限定符做到。
这种方式更有利于我们更好的管理每一个类。
举个生活中的例子,假设现在游客们要去参观兵马俑。现在有两种参观形式,
第一种:兵马俑周围没有警戒线,游客们可以随意下坑与兵马俑进行亲密的接触;
第二种:兵马俑周围有警戒线和保安,游客们只能被允许在警戒线之外参观兵马俑,一旦你先冲破警戒线与兵马俑近距离接触,就会被保安强制隔开。
大家觉得那种方式更好?毫无疑问是第二种!
兵马俑作为我国的宏伟景象之一,是不容许他人随意的破坏的。所以赋予游客一定的权限是比较的正确的做法。这样就既能保护文物,又能让游客们感受到兵马俑宏伟的气场,一举两得。
相信经过上面的例子,大家就可以理解为什么在类中需要设置访问权限了!
4.2 访问限定符
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。

【访问限定符说明】
- public修饰的成员在类外可以直接被访问
- protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
- 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
- 如果后面没有访问限定符,作用域就到 } 即类结束。
- class的默认访问权限为private,struct为public(因为struct要兼容C)
注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别
常出现的面试题:
问题:C++中struct和class的区别是什么?
解答:C++需要兼容C语言,所以C++中struct可以当成结构体使用。另外C++中struct还可以用来
定义类。和class定义类是一样的,区别是struct定义的类默认访问权限是public,class定义的类
默认访问权限是private。
4.3 封装
这里也会出现一个面试题:
面向对象的三大特性:封装、继承、多态。
在类和对象阶段,主要是研究类的封装特性,那什么是封装呢?
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
封装本质上是一种管理,让用户更方便使用类。 比如:对于电脑这样一个复杂的设备,提供给用
户的就只有开关机键、通过键盘输入,显示器,USB插孔等,让用户和计算机进行交互,完成日
常事务。但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件。
对于计算机使用者而言,不用关心内部核心部件,比如主板上线路是如何布局的,CPU内部是如
何设计的等,用户只需要知道,怎么开机、怎么通过键盘和鼠标与计算机进行交互即可。因此计
算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以
及键盘插孔等,让用户可以与计算机进行交互即可。
在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来
隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用。
5. "类"的作用域
类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用::作用域操作符指明成员属于哪个类域。
class Person
{
public:void PrintPersonInfo();
private:char _name[20];char _gender[3];int _age;
};//这里时声明和定义分离
// 这里需要指定PrintPersonInfo是属于Person这个类域
void Person::PrintPersonInfo()
{cout << _name << " "<< _gender << " " << _age << endl;
}
6. "类"的实例化(重点理解)
用类类型创建对象的过程,称为类的实例化
-
类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没
有分配实际的内存空间来存储它;比如:入学时填写的学生信息表,表格就可以看成是一个
类,来描述具体学生信息。 -
一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量。
int main()
{Person._age = 100; // 编译失败:error C2059: 语法错误:“.”return 0;
}
Person类是没有空间的,只有Person类实例化出的对象才具有空间。
- 做个比方,如果我们将"类"比作是"设计图纸",那用类实例化出的"对象"就是使用设计图纸建造的一栋栋房子。"设计图纸"是不占据实际的占地面积的,只有房子才占据实际的占地面积。同样,类也是一个设计,实例化出的对象才能存储实际的数据,占用物理空间!


像上面的定义的一样,变量man才有实际从存储空间,里面的数据才能被访问!
7. "类"对象模型
7.1 如何计算类对象的大小
class A
{
public:void PrintA(){cout << _a << endl;}private:char _a;
};
问题:类中既可以有成员变量,又可以有成员函数,那么一个类的对象中包含了什么?如何计算
一个类的大小?
这里我们跟着答案来逐步解析:

可以看到A类的大小为1字节。从这个结果我们可以知道,成员函数的大小是不算在类的大小中的。
🍉同样,在C++中,类的在内存中的存储也遵从内存对齐的原则!
为了验证我们这个理论,我们可以这样测试:

对内存对齐熟悉的读者,最很容易得以验证了。(这里我就不再过多赘述了,大家可以翻看我往期的文章——结构体)
7.2 类对象的存储方式猜测
- 对象中包含类的各成员

缺陷:每个对象的成员变量是不同的,但是调用同一份函数,如果按照上面此种方式存储,当一个类中创建了多个对象,每一个对象都会保存一份函数,相同函数保存多次,浪费空间,那么该如何解决?
- 函数只保存一份,在对象中保存存放函数的地址

- 只保存成员变量,成员函数存放在公共的代码段

问题:对于上面三种存储方式,那计算机到底是按照哪种方式了存储的呢?
这里我就直接告诉大家答案,是方案三。
OK,理解了上面类的对象模型后,我们来看一下下面代码:
// 类中既有成员变量,又有成员函数
class A1 {
public:void f1(){}
private:int _a;
};// 类中仅有成员函数
class A2 {
public:void f2() {}
};// 类中什么都没有---空类
class A3
{};
请问:上面每个类的大小是多少?

想必大家对最后两个类的大小有疑问,这里明明没有成员变量,为什么这里的大小不是0?
那我们可以这样想,假如这个类的大小是0,那么通过这个类创建出的对象大小也是0。可是编译器是支持我们也一个空类的,也就意味着这个类创建的对象一定存储在内存中,如果大小为0,那就代表对象不在内存中,编译器就无法在内存找到这个变量,为此编译器采用了1个字节大小用作空类对象的标记。
为此,我们可以做一个总结:
一个类的大小,实际就是该类中"成员变量"大小之和,当然注意内存对齐。
注意空类的大小,空类比较特殊,编译器会给空类一个字节来唯一标识这个类的对象。
8. this指针
8.1 this指针的引出
我们先来定义一个日期类Date
class Date
{
public:void Init(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.Init(2022, 1, 11);d2.Init(2022, 1, 12);d1.Print();d2.Print();return 0;
}
对于上述类,有这样的一个问题:
Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,那当d1调用 Init 函
数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?
C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏
的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”
的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编
译器自动完成。
8.2 this指针的特性
- this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。
- 只能在“成员函数”的内部使用
- this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给
this形参。所以对象中不存储this指针。(this指针是存放在栈区) - this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传
递,不需要用户传递。

【注意】我们只能在成员函数内部显示使用this指针,不能在成员函数的形参使用this指针和显示传递this指针变量。

红色标记的地方具有错误,请大家在使用this指针时,注意一些细节。
8.3 关于this指针的面试题
// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:void Print(){cout << "Print()" << endl;}
private:int _a;
};int main()
{A* p = nullptr;p->Print();return 0;
}
答案:C
// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:void PrintA() {cout<<_a<<endl;}
private:int _a;
};int main()
{A* p = nullptr;p->PrintA();return 0;
}
答案:B
原因:针对于题目一,我们定义了一个 A类型的指针p,指针p的值设为空。很多人就会卡在下面的这一段代码
p->PrintA();,这个不是空指针的解引用吗?程序运行一定会崩溃的,所以有的人两道题目都会选B。可事实真的如此吗?这里并没有出现空指针的解引用,因为我们说过,类的成员函数是存放在公共代码区的,是不属于任何一个对象独有的!
之所以题目一中调用成员函数没有问题的原因是它未解引用this指针,而题目二中其就是对空指针解引用了,因为此时this指针的值就是指针p的值。
好了到这里,本文就讲解完毕了。
如果觉得本文写的还不错的话,麻烦给偶点个赞吧!!!

相关文章:
【C++】踏上C++的学习之旅(六):深入“类和对象“世界,掌握编程的黄金法则(一)
文章目录 前言1. "面向过程"和"面向对象"的碰撞1.1 面向过程1.2 面向对象 2. "类"的引入3. "类"的定义3.1 🍉语法展示:3.2 "类"的两种定义方式3.3 "类"的命名规则 4. 类的访问限定符以及封…...
【物联网技术】ESP8266 WIFI模块在STA模式下作为TCP客户端上电自动进入透传数据模式
前言:讲解如何在ESP8266 WIFI模块在STA模式下作为TCP客户端与网络调试助手(TCP服务器)上电自动进入透传数据模式,而不需重新再发指令配置进入透传模式。 演示视频: ESP8266 WIFI模块在STA模式下作为TCP客户端上电自动进入透传数据模式 wifi模块在STA模式下作为TCP客户端相…...
重构代码之用委托替代继承
在代码重构中,用委托替代继承 是一种用于改善代码设计和提高灵活性的重要技术。它的核心思想是,将子类与父类的直接继承关系转换为委托关系,即子类不再直接继承父类,而是通过持有父类的实例来访问所需的功能。 一、为什么需要用委…...
软件设计师下午题UML15分
一、涉及到的图及对应关系 二、例题 1.用例图和类图的例题 解析及答案 2.状态图和类图的例题 3.通信图和类图例题 例题...
css background-image背景图片轮播
1、CSS背景样式有以下几种: 背景颜色(background-color):设置元素的背景颜色。背景图片(background-image):设置元素的背景图片。背景重复(background-repeat)ÿ…...
java---认识异常(详解)
还有大家来到权权的博客~欢迎大家对我的博客提出意见哦,有错误会及时改进的~点击进入我的博客主页 目录 一、异常的概念及体系结构1.1 异常的概念1.2 异常的体系结构1.3异常的分类 二、异常的处理2.1防御式编程2.2 异常的抛出2.3 异常的捕获2.3.1异常声明throws2.3.…...
Linux基础学习笔记
Linux基础学习笔记 Linux目录结构: 具体的目录结构: /bin [重点] (/usr/bin 、 /usr/local/bin) • 是Binary的缩写, 这个目录存放着最经常使用的命令 /home [重点] • 存放普通用户的主目录,在Linux中每个用户都有一个自己的目录,一…...
自动泊车端到端算法 ParkingE2E 介绍
01 算法介绍 自主泊车是智能驾驶领域中的一项关键任务。传统的泊车算法通常使用基于规则的方案来实现。因为算法设计复杂,这些方法在复杂泊车场景中的有效性较低。 相比之下,基于神经网络的方法往往比基于规则的方法更加直观和多功能。通过收集大量专家…...
《手写Spring渐进式源码实践》实践笔记(第十七章 数据类型转换)
文章目录 第十七章 数据类型转换工厂设计实现背景技术背景Spring数据转换实现方式类型转换器(Converter)接口设计实现 业务背景 目标设计实现代码结构类图实现步骤 测试事先准备属性配置文件转换器工厂Bean测试用例测试结果: 总结 第十七章 数…...
W3C HTML 活动
关于W3C(万维网联盟)的HTML活动,我们可以从HTML的不同版本的发展历程中了解其主要的活跃时期和贡献。 HTML 2.0:这个版本的HTML是由Internet工程工作小组(IETF)的HTML工作组于1996年开发的。它是HTML的早期…...
机器学习—为什么我们需要激活函数
如果我们使用神经网络中每个神经元的线性激活函数,回想一下这个需求预测示例,如果对所有节点使用线性激活函数,在这个神经网络中,事实证明,这个大神经网络将变得与线性回归没有什么不同,所以这将挫败使用神…...
软考系统架构设计师论文:论软件的可靠性评价
试题四 论软件的可靠性评价 软件可靠性评价是软件可靠性活动的重要组成部分,既适用于软件开发过程,也可针对最 终软件系统。在软件开发过程中使用软件可靠性评价,可以使用软件可靠性模型,估计软件当前的可靠性,以确认是否可以终止测试并发布软件,同时还可以预计软件要达…...
C++:线程(thread)的创建、调用及销毁
在 C 中,线程的管理主要依赖于标准库 std::thread,自 C11 起,这一功能被标准化,使得我们能够更加方便地创建、管理和销毁线程。这里我们详细讲解线程的创建、调用和销毁流程。 1. 线程的创建 创建线程通常是为了在单独的线程中执…...
关于随身wifi,看了再决定要不要买!2024年最受欢迎的随身wifi品牌推荐!
话费、流量费缴纳起来肉疼,毕竟不是每个月都有很大需求,主打一个该省省该花花。特别是短租人群、在校学生、出差或旅游的人群、追求高性价比的人群,随身Wifi特别实用,出门当WiFi,在家当宽带,两不耽误&#…...
SpringMVC总结 我的学习笔记
SpringMVC总结 我的学习笔记 一、SpringMVC简介1.MVC2.SpringMVC概述3. SpringMVC中的核心组件4.SpringMVC核心架构流程 二、SpringMVC框架实例具体实现使用注解实现 四、数据处理及跳转1.结果跳转方式2.处理器方法的参数与返回值处理提交数据数据显示到前端 五、RestFul风格1.…...
DevCheck Pro手机硬件检测工具v5.33
前言 DevCheck Pro是一款手机硬件和操作系统信息检测查看工具,该软件的功能非常强大,为用户提供了系统、硬件、应用程序、相机、网络、电池等一系列信息查看功能 安装环境 [名称]:DevCheckPro [版本]:5.33 [大小]&a…...
数据分析ReAct工作流
让我用一个数据分析项目的例子来展示plan-and-execute框架的应用。这个例子会涉及数据处理、分析和可视化等任务。 from typing import List, Dict, Any from dataclasses import dataclass import json from enum import Enum import logging from datetime import datetime#…...
Rust-AOP编程实战
文章本天成,妙手偶得之。粹然无疵瑕,岂复须人为?君看古彝器,巧拙两无施。汉最近先秦,固已殊淳漓。胡部何为者,豪竹杂哀丝。后夔不复作,千载谁与期? ——《文章》宋陆游 【哲理】文章…...
Flutter鸿蒙next 中的 Expanded 和 Flexible 使用技巧详解
在 Flutter 开发中,Expanded 和 Flexible 是两个非常常用的布局控件,它们可以帮助开发者更加灵活地管理 UI 布局的空间分配。虽然它们看起来非常相似,但它们的功能和使用场景有所不同。理解这两者的区别,能帮助你在构建复杂 UI 布…...
【微信小游戏学习心得】
这里是引用 微信小游戏学习心得 简介了解微信小游戏理解2d游戏原理数据驱动视图总结 简介 本人通过学习了解微信小游戏,学习微信小游戏,加深了对前端框架,vue和react基于数据驱动视图的理解,及浏览器文档模型和javaScript之间的关…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...
从物理机到云原生:全面解析计算虚拟化技术的演进与应用
前言:我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM(Java Virtual Machine)让"一次编写,到处运行"成为可能。这个软件层面的虚拟化让我着迷,但直到后来接触VMware和Doc…...




