【C++】类与对象

文章目录

  • 1. 面向过程与面向对象
  • 2. 类(class)
    • 类的作用域
  • 3. 访问限定符
    • 封装
  • 4. 类的实例化
  • 5. this指针
  • 6. 默认成员函数
    • 6.1 构造函数
    • 6.2 析构函数
    • 6.3 拷贝构造函数

1. 面向过程与面向对象

C语言是面向过程(procedure-oriented)的语言,分析出求解问题的步骤,通过函数调用逐步解决问题。以洗衣服举例,需要很多个步骤:
在这里插入图片描述

C++是面向对象(object-oriented)的语言,将一件事情拆分成不同的对象,靠对象之间的交互完成。洗衣服这件事可以拆分成三个对象:人、衣服和洗衣粉,可能也有洗衣机,洗衣服这个过程是由这三个或四个对象之间交互完成的。

2. 类(class)

C语言结构体中只能定义变量,在C++中结构体内不仅可以定义变量,也可以定义函数。

struct Person {char name[20];int age;char gender;int height;int weight;char introduction[100];void showInfo() {cout << name << " - " << age << " - " << gender << endl;}void sleep() {}void washCloth() {}void readBook() {}void work() {}void study() {}
};

可以这么做是因为C++需要兼容C,事实上C++更喜欢用class关键字表示一个类:

class Person
{// 类体由变量和函数组成
};

类中的变量称为类的属性或成员变量,类中的函数称为类的方法或成员函数。可以将成员的声明和定义一起放在类中,如果成员函数放在类中定义,编译器可能会将其当成内联函数处理;也可以将类成员的声明和定义分开,类中的成员变量和成员函数的声明放在.h头文件,成员函数的定义放在.cpp文件。

类的作用域

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

class Person {char name[20];int age;char gender;int height;int weight;char introduction[100];void showInfo();void sleep();void washCloth();void readBook();void work();void study();
};void Person::showInfo() {cout << name << " - " << age << " - " << gender << endl;
}

3. 访问限定符

访问限定符用于确定类成员的访问权限

  1. public:被public修饰的成员在类外可以被访问;
  2. protected:被protected修饰的成员在类外不能被访问,但可以在继承的子类中被访问;
  3. private:被private修饰的成员在类外不能被访问。

class关键字定义类的默认访问权限是private,这是因为面向对象三大特性之一的封装。struct关键字定义类的默认访问权限是public,因为需要兼容C。

封装

面向对象的三大特性:封装、继承、多态。封装是将数据和操作数据的方法进行结合,通过访问权限来隐藏对象内部的属性和实现细节,控制哪些函数可以在类外部直接被使用,仅对外公开接口来和对象进行交互。

封装本质上是一种管理,让用户更方便使用类。比如对于电脑这样一个复杂的设备,提供给用户的就只有开关机键、通过键盘输入,显示器,USB插孔等,让用户和计算机进行交互。对于计算机使用者而言,不用关心内部核心部件,主板上线路是如何布局的,CPU内部是如何设计的。

class Person {private:char name[20];int age;char gender;int height;int weight;char introduction[100];public:void showInfo();void sleep();void washCloth();void readBook();void work();void study();
};void Person::showInfo() {cout << name << " - " << age << " - " << gender << endl;
}

4. 类的实例化

用类类型创建对象的过程,称为类的实例化。类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它。一个类可以实例化出多个对象,实例化出的对象占用实际的内存空间,存储类成员变量。

int main() {Person p1;Person p2;Person p3;
}

计算对象的内存大小与计算结构体的大小一致,可以看这篇文章计算结构体的大小了解,简单地说就是按计算结构体大小的方式来计算类成员变量的大小。成员函数不会包括在内,因为成员函数是n个对象共用的,存放在公共代码区。另外空类比较特殊,它也有大小,占用1个字节空间。

5. this指针

this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给
this形参,因此this指针并不存放在对象中,而是在栈中(可能也在寄存器中,取决于编译器)。
在这里插入图片描述
this指针的类型:类的类型* const,只能在“成员函数”的内部使用。this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要程序员手动传递。

下面两段程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行

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

C.正常运行,表面存在空指针问题,但成员函数中并没有使用其它成员,仅仅只是打印一个字符串,不会导致空指针访问。

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

B.运行崩溃,成员函数中使用了成员变量,实际上是this指针访问的成员,造成了空指针。

6. 默认成员函数

如果一个类中什么成员都没有,简称为空类。空类并不是什么都没有,编译器会自动生成6个默认成员函数。默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

1. 构造函数:初始化对象;
2. 析构函数:清理对象中申请的动态内存;
3. 拷贝构造:使用同类对象创建另一个对象;
4. 赋值重载:把一个对象赋值给另一个对象;

5. 普通对象取地址重载;
6. const对象取地址重载。

后面两个取地址重载很少用。

6.1 构造函数

构造函数是一个特殊的成员函数,名字与类名相同,创建对象时由编译器自动调用,并不是开空间创建对象,而是完成对象的初始化工作。

class Date {
private:int year;int month;int day;
public:Date() { // 无参构造}Date(int y, int m, int d) {year = y;month = m;day = d;}
};int main() {Date date1;Date date2(2024, 3, 11);return 0;
}

如果通过无参构造函数创建对象,后面不用跟括号,否则就成了函数声明。

构造函数特征如下:

  1. 函数名与类名相同。
  2. 无返回值。
  3. 对象实例化时编译器自动调用对应的构造函数。
  4. 构造函数可以重载。
  5. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
  6. 无参的构造函数、全缺省的构造函数、编译器默认生成的构造函数都称为默认构造函数,在一个类中这三个默认构造函数只能存在其中一个,因为这三个都可以不用传参,如果同时存在会产生调用歧义。
class Date {
private:int year;int month;int day;
public:Date() { // 与下面全缺省的构造函数存在冲突}Date(int y = 2024, int m = 2, int d = 22) {year = y;month = m;day = d;}
};

在这里插入图片描述

  1. 编译器生成默认的构造函数,会对类中其它自定类型成员调用的它的默认构造
    函数。比如Date类中如果包含一个Time类成员:
class Time {
private:int hour;int minute;int second;
public:Time() {cout << "Time()" << endl;}
};
class Date {
private:int year;int month;int day;Time time;
public:Date(int y = 2024, int m = 2, int d = 22) {cout << "Date(int, int, int)" << endl;year = y;month = m;day = d;}
};int main() {Date date;return 0;
}

在这里插入图片描述

由于默认生成的构造函数不会进行有效的初始化,给的是随机值,所以C++11开始可以给内置类型(int/char/double等)成员在类中声明时给默认值,如果没有指定初始化则初始化成默认值。

class Date
{
private:int _year = 1970;int _month = 1;int _day = 1;Time _time;
};

6.2 析构函数

析构函数不是完成对对象本身的销毁,对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

析构函数的特征如下:

  1. 析构函数名是在类名前加上字符 ~。
  2. 无参数和无返回值类型。
  3. 一个类只能有一个析构函数,若未显式定义,系统会自动生成默认的析构函数。
  4. 析构函数不能重载。
  5. 对象生命周期结束时,C++编译系统系统自动调用析构函数。
typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 4){_array = (DataType*)malloc(sizeof(DataType) * capacity);if (NULL == _array){perror("Stack malloc failed.");return;}_capacity = capacity;_size = 0;}~Stack(){if (_array){free(_array);_array = NULL;_capacity = 0;_size = 0;}}
private:DataType* _array;int _capacity;int _size;
};
  1. 编译器生成的默认析构函数,对自定义类型的成员调用它的析构函数。
class Time
{
public:~Time(){cout << "~Time()" << endl;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:int _year = 1970;int _month = 1;int _day = 1;Time _time;
};
int main()
{Date d;return 0;
}
  1. 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数。有资源申请时(malloc),一定要写,否则会造成资源泄漏。

6.3 拷贝构造函数

拷贝构造函数创建一个与已存在对象一样值的新对象。参数只有单个形参,该形参是对本类类型对象的引用,且一般常用const修饰,在用已存在的类型对象创建新对象时由编译器自动调用。

拷贝构造函数特征如下:

  1. 拷贝构造函数是构造函数的一个重载形式。
class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d)  {_year = d._year;_month = d._month;_day = d._day;}
private:int _year;int _month;int _day;
};
  1. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式的话编译器直接报错,因为会引发无穷递归调用。这是错误写法,传值会引发无穷递归:
 Date(const Date d)  {_year = d._year;_month = d._month;_day = d._day;}

原因如下:

void Test1(const Date d) {}
void Test2(const Date& d) {}
int main() {Date date1;Test1(date1); // 调用Test1传值会首先调用拷贝构造Test2(date1); // 传引用不会去调用拷贝构造
}

在这里插入图片描述
所以说拷贝构造的形参不使用引用,会引发无穷递归:
在这里插入图片描述
初始化date2时传值而不传引用,调用了一层拷贝构造后,拷贝构造本身继续传值继续调用拷贝构造引发无穷递归,现在这样写的话vs直接爆红,编译都不给编译。

  1. 若未显式定义拷贝构造,默认的拷贝构造函数按字节序完成拷贝,这种拷贝叫做浅拷贝(值拷贝)。如果类中有需要申请内存资源的成员(需要malloc的成员),默认的拷贝构造无法完成拷贝,需要自己显示定义完成深拷贝。比如:
typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 4){_array = (DataType*)malloc(sizeof(DataType) * capacity);if (NULL == _array){perror("Stack malloc failed.");return;}_capacity = capacity;_size = 0;}~Stack(){if (_array){free(_array);_array = NULL;_capacity = 0;_size = 0;}}
private:DataType* _array;int _capacity;int _size;
};

使用默认的拷贝构造传入stack1初始化stack2,stack2的array仅仅只是把stack1的array地址值拷贝过来了,意味着共用同一块内存。
在这里插入图片描述
显示定义拷贝构造为深拷贝的正确写法:

	Stack(const Stack& rStack) {_capacity = rStack._capacity;_size = rStack._size;_array = (DataType*)malloc(sizeof(DataType) * _capacity);memcpy(_array, rStack._array, _size);//for (int i = 0; i < _size; ++i) {//	_array[i] = rStack._array[i];//}}

在这里插入图片描述

为了提高程序效率,一般对象传参时,尽量使用引用类型;函数返回值根据实际场景,能用引用尽量使用引用。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

“成像光谱遥感技术中的AI革命:ChatGPT应用指

遥感技术主要通过卫星和飞机从远处观察和测量我们的环境&#xff0c;是理解和监测地球物理、化学和生物系统的基石。ChatGPT是由OpenAI开发的最先进的语言模型&#xff0c;在理解和生成人类语言方面表现出了非凡的能力。本文重点介绍ChatGPT在遥感中的应用&#xff0c;人工智能…

数字脉搏:互联网的演进与社会脉络

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

React-路由小知识

1.默认路由 说明&#xff1a;当访问的是一级路由时&#xff0c;默认的二级路由组件可以得到渲染&#xff0c;只需要在二级路由的位置去掉path,设置index.属性为true。 2.404路由 说明&#xff1a;当浏览器输入ul的路径在整个路由配置中都找不到对应的pth,为了用户体验&#x…

【蓝桥杯】路径之谜(DFS)

一.题目描述 小明冒充 X 星球的骑士&#xff0c;进入了一个奇怪的城堡。 城堡里边什么都没有&#xff0c;只有方形石头铺成的地面。 假设城堡地面是 nn 个方格。如下图所示。 按习俗&#xff0c;骑士要从西北角走到东南角。可以横向或纵向移动&#xff0c;但不能斜着走&#x…

如何在Linux使用Docker部署Firefox并实现无公网IP访问本地浏览器

文章目录 1. 部署Firefox2. 本地访问Firefox3. Linux安装Cpolar4. 配置Firefox公网地址5. 远程访问Firefox6. 固定Firefox公网地址7. 固定地址访问Firefox Firefox是一款免费开源的网页浏览器&#xff0c;由Mozilla基金会开发和维护。它是第一个成功挑战微软Internet Explorer浏…

基于React低代码平台开发:直击最新高效应用构建

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》《项目实战》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录…

浅析开源内存数据库Fastdb

介绍&#xff1a; Fastdb是免费开源内存数据库&#xff0c;其优秀的性能&#xff0c;和简洁的C代码&#xff0c;让我学习使用过程中收益颇多&#xff0c;但是国内中文相关研究的文章相当稀少&#xff0c;外文我查询相当不便。有兴趣的朋友可以通过以下网站访问&#xff1a;Mai…

Redis 内存的优化

目录 前言 Redis 的内存碎片问题 判断Redis 内存碎片 如何清理内存碎片&#xff1f; 前言 我想讲一下怎么提高Redis 内存的利用率&#xff0c;redis 的数据是保存在内存中。对内存的利用率低&#xff0c;意味着存的数据很少&#xff0c;并不意味着就没有内存了&#xff0c…

【办公类-21-09】三级育婴师 视频转文字docx(等线小五单倍行距),批量改成“宋体小四、1.5倍行距、蓝色字体”

作品展示&#xff1a; 背景需求&#xff1a; 一、视频处理 1、育婴师培训的现场视频 2、下载视频&#xff0c;将视频换成考题名称 二、音频 视频用格式工厂转成MP3音频 3、转文字doc 把音频放入“网易云见外工作台”转换为“文字" 等待5分钟&#xff0c;音频文字会被写…

工地安全反光衣穿戴监测报警摄像机

工地安全反光衣穿戴监测报警摄像机是为了提高工地施工人员的安全意识和监管效率而设计的。这种设备结合了反光衣、监测系统和报警摄像机的功能&#xff0c;可以有效减少工地事故的发生。 首先&#xff0c;工地安全反光衣是一种具有高度可见度的服装&#xff0c;能够使穿戴者在夜…

混合测试写一写

题目 服务器IP地址规划&#xff1a;client&#xff1a;12.0.0.12/24&#xff0c;网关服务器&#xff1a;ens36:12.0.0.1/24、ens33&#xff1a;192.168.44.1/24&#xff0c;Web1&#xff1a;192.168.44.30/24&#xff0c;Web2&#xff1a;192.168.44.50/24&#xff0c;Nginx&am…

Draco点云压缩测试

ref&#xff1a;https://github.com/google/dracohttps://codelabs.developers.google.com/codelabs/draco-3d/index.html#6 Draco Draco 是一个用于编码压缩和解压缩 3D 几何网格和点云的库&#xff0c;从而改进 3D 图形的存储和传输该代码支持压缩点、连接信息、纹理坐标、颜…

男人的玩具系统wordpress外贸网站主题模板

垂钓用品wordpress外贸模板 鱼饵、鱼竿、支架、钓箱、渔线轮、鱼竿等垂钓用品wordpress外贸模板。 https://www.jianzhanpress.com/?p3973 身体清洁wordpress外贸网站模板 浴盐、防蚊液、足部护理、沐浴液、洗手液、泡澡用品wordpress外贸网站模板。 https://www.jianzhan…

【恒源智享云】conda虚拟环境的操作指令

conda虚拟环境的操作指令 由于虚拟环境经常会用到&#xff0c;但是我总忘记&#xff0c;所以写个博客&#xff0c;留作自用。 在恒源智享云上&#xff0c;可以直接在终端界面输入指令&#xff0c;例如&#xff1a; 查看已经存在的虚拟环境列表 conda env list查看当前虚拟…

隐私与创新的交汇点:Partisia Blockchain 重绘技术蓝图

正当我们在这个信息泛滥的时代寻找稳固的信任锚点时&#xff0c;区块链技术应运而生&#xff0c;然而&#xff0c;正如任何科技革命都会遇到的挑战&#xff0c;一个重要的问题摆在了我们面前&#xff1a;如何在不牺牲个人隐私的前提下&#xff0c;享受区块链技术带来的好处&…

【AI视野·今日NLP 自然语言处理论文速览 第八十四期】Thu, 7 Mar 2024

AI视野今日CS.NLP 自然语言处理论文速览 Thu, 7 Mar 2024 Totally 52 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers The Heuristic Core: Understanding Subnetwork Generalization in Pretrained Language Models Authors Adith…

python模块(二)

time模块 时间戳格式 import time data_timetime.time() print(data_time) #1702546257.544845 print(type(data_time)) #<class float> #打印自1970年到现在的时间 1702546257.544845 #打印123&#xff0c;每一次停4s while True:print(123)time.sleep(4)…

小程序分账方案:实现商户分账的简便与灵活

随着移动支付的普及和小程序的快速发展&#xff0c;越来越多的商家选择在微信小程序上开展业务。然而&#xff0c;对于一些有多个分账方的商户而言&#xff0c;如何实现快速、准确和灵活的资金分账成为了一个挑战。本文将介绍一种高效的小程序分账方案&#xff0c;帮助商户轻松…

python基础及网络爬虫

网络爬虫(Web crawler)&#xff0c;有时候也叫网络蜘蛛(Web spider)&#xff0c;是指这样一类程序——它们可以自动连接到互联网站点&#xff0c;并读取网页中的内容或者存放在网络上的各种信息&#xff0c;并按照某种策略对目标信息进行采集&#xff08;如对某个网站的全部页面…

「CISP题库精讲」CISP题库习题解析精讲20道

前言 本篇主要对CISP教材第九章《计算环境安全》的一些习题进行讲解&#xff0c;包括20道题&#xff0c;这里只是部分习题&#xff0c;针对第九章可能会多写几章的内容&#xff0c;如果我发布的这些习题里面没有你想找的那道题&#xff0c;你也可以直接私信我&#xff0c;我加…