C++初阶语法——类和对象

前言:C语言中的结构体,在C++有着更高位替代者——类。而类的实例化叫做对象。
本篇文章不定期更新扩展后续内容。

目录

  • 一.面向过程和面向对象初步认识
  • 二.类
    • 1.C++中的结构体
    • 2.类的定义
      • 类的两种定义方式
    • 3.类的访问限定符及封装
      • 访问限定符说明
    • 4.类的实例化
      • 对象只存储成员变量,不存储成员函数
      • 成员函数存储在公共代码区
    • 5.this指针
  • 三.六大默认成员函数
    • 1.构造函数
      • 构造函数特点(重点)
      • 默认构造函数(重点)
      • 初始化列表
    • 2.析构函数
      • 析构函数特点

一.面向过程和面向对象初步认识

在学习C语言的时候,我就时常听说过面向过程和面向对象,但是对这两个概念的认知非常模糊,那么这两者有什么区别呢?

C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
而C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。我们不需要关注过程是怎么完成的,我们只需要关注对象间的交互。
面向对象有3大特性——封装,继承,多态。

二.类

1.C++中的结构体

C语言中结构体中只能定义变量,而在C++中,结构体中不仅能定义变量,还可以定义函数(struct升级成了类)。

以数据结构——栈为例:
直接在结构体内定义函数。
实例化对象时,无需再写struct,只需写结构体名。

#include<iostream>
using namespace std;
typedef struct Stack {int* a;int capacity;int top;void Init()   //定义函数{a = nullptr;capacity = 0;top = 0;}
}ST;
int main()
{Stack s1; // 无structs1.Init();return 0;
}

2.类的定义

在C++中,类更喜欢用class而非struct。
这两者在默认访问限定上有些区别,struct默认为public,而class默认为private,更符合面向对象的要求。这也是为什么更喜欢使用class。该点在下文默认访问限定符也会讲解。

class Classname
{//类体:成员函数+成员变量};  //跟结构体一样有分号不要忘

class为定义类的关键字,Classname为类名,{}中为类的主体,类体中的内容称为类的成员,类中的变量称为类的属性或成员变量,类中的函数称为类的方法或成员函数。

类的两种定义方式

一种就是向上面的栈一样将函数声明定义都写在类里面,值得一提的是,这种函数会被编译器当成内联函数。
还有一种就是将类声明放在头文件中,在源文件中定义函数,但是需要注意的是,成员函数名前需要加类名::(域作用限定符),一般第二种用的更多。

//obj.h
#include<iostream>
using namespace std;typedef struct Stack {int* a;int capacity;int top;void Init();
}ST;//test.cpp
#include"obj.h"
void Stack::Init()  // 类名::
{a = nullptr;capacity = top = 0;
}

3.类的访问限定符及封装

C++实现封装的方式:用类将对象的属性(成员变量)和方法(成员函数)结合在一起,让对象更加完善,通过访问限定符选择性的将其接口提供给外部的用户使用。

共有3种访问限定符:在诸如php,java等语言中都有。
这里是引用

访问限定符说明

利用好访问限定符,可以有效保护好类中的数据,防止其他人随便访问。
1.public:公有的类成员可以在任何地方被访问。
protect:受保护的类成员则可以被其自身以及其子类和父类访问。
private:私有的类成员则只能被其定义所在的类访问。
(在学继承之前,protect和private使用起来没差)
2.struct默认为public,class默认为private。
3.访问权限作用域从该访问限定符开始到下一个访问限定符出现。
4.如果后面没有访问限定符,作用域到 } 为止。
5.一般情况下,成员变量都设置为private。

以日期类为例:

class Date {
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}
private:int _year;  //声明,没有定义,不占空间int _month;int _day;
};

4.类的实例化

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

以日期类为例:

class Date {
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}
private:int _year;  //声明,没有定义,不占空间int _month;int _day;
};int main()
{Date d1;  // 类的实例化Date d2, d3;  // 一个类可以实例化出多个对象//下面两行代码可行吗,为什么?//Date::_year = 1;  //并没有实例化对象,只是声明没有开空间,更不必说初始化了。//d1._year = 1; //实例化了呢?也不行,因为_year是私有成员变量,只能在Date类中更改。return 0;
}

对象只存储成员变量,不存储成员函数

上文说过,类的主体有两个:成员变量和成员函数。
但实际上实例化的对象中只存储成员变量,而成员函数存储在公共代码区。

请看下例代码(类的空间大小计算和结构体一样,遵循结构体内存对齐规则):

class Date {
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}
private:int _year;   //声明,没有定义,不占空间int _month;int _day;
};int main()
{Date s1;cout << sizeof(Date) << endl;cout << sizeof(s1) << endl;return 0;
}

控制台输出如下:
在这里插入图片描述
可以发现,12是只计算成员变量得到的结果,因此可以得知对象中并不存储成员函数。

之所以这样是因为成员函数对每个对象都是一样的,其会被存储在公共代码区,这样不必要在每次实例化对象时都存储一次成员函数,大大提高了程序效率。
在这里插入图片描述

成员函数存储在公共代码区

请看如下代码,各位觉得能够运行成功吗?

class Example
{
public:void Print(){cout << "Print()" << endl;}
private:int _a;int _b;
};
int main()
{Example* s1 = nullptr;s1->Print();  //空指针指向????return 0;
}

控制台显示如下:
在这里插入图片描述
运行成功了,为什么呢?上面不是空指针解引用问题吗,程序应该崩溃呀?
答:上面说过成员函数存储在公共代码区,直接向公共代码区call该函数的地址,不需要向对象s1中找东西,因此不会发生空指针解引用操作。

5.this指针

类的成员函数中都隐藏了一个this指针参数。
this在实参和形参位置不能显示写,但是可以在类里面显示的用。
this指针不可被更改.
this指针可以为空(就是上面成员函数存在公共代码区的例子)。
this指针存在栈帧里面。(不要误以为this存在对象中,this就是一个形参,跟普通形参一样存在栈帧里面)。

仍以日期类为例:

class Date {
public://this在实参和形参中不能显示地写//在类中可以显示地用(没什么价值)void Init(int year, int month, int day){_year = year;_month = month;_day = day;}/*void Init(Date* const this ,int year, int month, int day){this->_year = year;this->_month = month;this->_day = day;}*/
private:int _year;int _month;int _day;
};int main()
{Date d1;d1.Init(2023, 8, 11); //d1.Init(&d1,2023,8,11);return 0;
}

三.六大默认成员函数

C++中有六个默认成员函数,我们不写的话,它们会自动生成。

在这里插入图片描述

1.构造函数

构造函数最便捷的地方就是自动调用,可以在我们忘了初始化的时候发挥作用。

构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象
其特征如下:
1.函数名和类名相同
2.无返回值(不需要写void)。
3.对象实例化时编译器自动调用对应的构造函数。
4.构造函数可以重载。(可以写多个构造函数,提供多种初始化方式)

class Date {
public://构造函数,函数名和类名相同。Date(int year = 1, int month = 1, int day = 1) //全缺省参数{cout << "Date()" << endl;  // 借此观察构造函数是否被调用_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};int main()
{Date d1(2023,8,11); // 对象实例化时自动调用构造函数,一定记住!!! 实参可以任意更改//在对象d1后面接实参是构造函数的特殊的初始化规则。 //Date d2(); //不可以在对象后加括号而不给实参,因为编译器分不清你是在创建对象还是调用函数。return 0;
}

控制台输出如下:可以看到,我们并没有调用Date函数,Date函数在对象实例化时自动调用了。
在这里插入图片描述

构造函数特点(重点)

构造函数,是默认成员函数之一,我们不写,编译器也会自动生成。
编译生成的默认构造函数的特点:
1.我们写了就不会自动生成了,我们不写编译器会自动生成一个无参的默认构造函数
2.内置类型不会处理(C++11,支持声明时给缺省值,但是有了缺省值就会处理)
3.自定义类型的成员才会处理,会去调用这个成员的默认构造函数。(注意是默认构造函数,而非是构造函数)

(内置类型就是诸如int,double这种语言提供的类型,而自定义类型就是我们自己定义的类型,比如上文的Date。
需要注意的是:int* 是内置类型,Date* 也是内置类型。只要是指针就是内置类型)

默认构造函数(重点)

ps:这个地方刚开始学的时候理解起来挺难的,我被绕的晕头转向的。还是要多学多看代码啊。

无参的构造函数和全缺省的构造函数(此两者都是我们自己写的)都被称为默认构造函数,并且默认构造函数只能有一个。
共有3种默认构造函数:
1.无参的构造函数
2.全缺省的构造函数
3.我们没写编译器自动生成的构造函数。
总结:这3种默认构造函数有一个共同点,就是不传参就可以调用。
多个默认构造函数同时存在会有歧义。

如下图所示,编译器就会显示无默认构造函数。
在这里插入图片描述
而将Date写成全缺省就可以正常运行(对应上文的全缺省的构造函数是默认构造函数)
在这里插入图片描述

初始化列表

2.析构函数

析构函数:与构造函数的作用相反,析构函数不是完成对对象本身的销毁,局部对象的销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作(malloc,realloc出来的空间等)。
析构函数的特性:
1.析构函数名是在类名前加上字符~
2.无参数无返回值
3.一个类只能有一个析构函数。若未显示定义(我们没写),系统会自动生成默认的析构函数。注意:析构函数不能重载。
4.对象声明周期结束时,C++编译系统自动给调用析构函数。
5.后定义的对象先析构(栈帧)。

析构函数特点

跟构造函数类似,析构函数具有以下特点:
1.我们写了就不会自动生成了,我们不写编译器会自动生成一个析构函数。
2.内置类型成员不会处理。
3.自定义类型成员会调用这个成员的析构函数。

·总结:一般情况下都需要我们自己写构造函数,决定初始化方式。而成员变量全是自定义类型时,可以考虑不写构造函数。

文末BB:对哪里有问题的朋友,尽管在评论区留言,若哪里写的有问题,也欢迎朋友们在评论区指出,博主看到后会第一时间确定修改。最后,制作不易,如果对朋友们有帮助的话,希望能给博主点点赞和关注.

在这里插入图片描述

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

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

相关文章

微信开发之获取收藏夹列表的技术实现

简要描述&#xff1a; 获取收藏夹内容 请求URL&#xff1a; http://域名地址/weChatFavorites/favSync 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数…

【面试八股文】每日一题:谈谈你对异常的理解

每日一题-Java核心-谈谈你对异常的理解【面试八股文】 异常是程序在运行过程中出现的错误或不正常的情况。当程序执行过程中遇到无法处理的错误或者不符合预期的情况&#xff0c;就会抛出异常。异常可以分为两种类型&#xff1a;受检异常和非受检异常。 受检异常是指在程序编译…

SqlServer基础之(触发器)

概念&#xff1a; 触发器&#xff08;trigger&#xff09;是SQL server 提供给程序员和数据分析员来保证数据完整性的一种方法&#xff0c;它是与表事件相关的特殊的存储过程&#xff0c;它的执行不是由程序调用&#xff0c;也不是手工启动&#xff0c;而是由事件来触发&#x…

Semantic Kernel 入门系列: Planner 规划器

Semantic Kernel 的一个核心能力就是实现“目标导向”的AI应用。 目标导向 “目标导向”听起来是一个比较高大的词&#xff0c;但是却是实际生活中我们处理问题的基本方法和原则。 顾名思义&#xff0c;这种方法的核心就是先确定目标&#xff0c;然后再寻找实现目标的方法和…

Photoshop 2023 25.0beta「Mac」

Photoshop 2023是一款专业图像处理软件&#xff0c;它主要用于图像编辑、合成和设计等方面。 Photoshop beta创新式填充的功能特色包括&#xff1a; 自动识别和删除对象&#xff1a;该功能可以自动识别图像中的对象&#xff0c;并用周围的图像填充空白部分&#xff0c;使图像看…

从零到精通:学习这些R语言必学包成为数据分析高手!

一、操作数据 ❝ tidyverse ❞ tidyverse是一个强大的R语言数据分析工具集&#xff0c;包含了多个核心包。其中包括ggplot2用于数据可视化、dplyr用于数据处理和转换、tidyr用于数据整理和重塑、readr用于数据导入和读取、purrr用于函数式编程、stringr用于字符串处理等。 ❝ d…

认识FFMPEG框架

FFMPEG全称: Fast Forward Moving Picture Experts Group (MPEG:动态图像专家组) ffmpeg相关网站: git://source.ffmpeg.org/ffmpeg.git http://git.videolan.org/?pffmpeg.git https://github.com/FFmpeg/FFmpeg FFMPEG框架基本组件: AVFormat , AVCodec, AVDevice, AVFil…

Zabbix监控系统

目录 一、zabbix简介 1.1 zabbix 是什么&#xff1f; 1.2 zabbix 监控原理 二、安装zabbix 5.0 2.1 部署 zabbix 服务端 2.2 部署 zabbix 客户端 2.3 自定义监控内容 作为一个云计算行业从业人员&#xff0c;需要会使用监控系统查看服务器状态以及网站流量指标&#xff…

实力认证!TDengine 入选 Gartner 中国数据分析与人工智能技术成熟度曲线

近日&#xff0c;国际权威研究机构 Gartner 发布了《2023 年中国数据分析及人工智能技术成熟度曲线》&#xff08;即《Hype Cycle for Data, Analytics and AI in China, 2023》&#xff09;报告&#xff0c;TDengine 成功入选实时数据管理领域代表产品。 作为评估全球新技术成…

【MySQL安装】卸载与安装MySQL 5.7.X版本

最近由于各种原因&#xff0c;需要重新安装MySQL。之前我的版本是8.0版本&#xff0c;现在装的5.7版本。记录一下自己的安装过程。 目录 1、卸载MySQL8.0 2、安装MySQL5.7 1、卸载MySQL8.0 如何彻底卸载MySQL_mysql 完全卸载_m0小麦麦的博客-CSDN博客相信不少小伙伴们在安装…

EasyPoi导出 导入(带校验)简单示例 EasyExcel

官方文档 : http://doc.wupaas.com/docs/easypoi pom的引入: <!-- easyPoi--><dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-spring-boot-starter</artifactId><version>4.0.0</version></dep…

Java基础入门篇——数组初识

一、数组 1.假设某公司有100个员工&#xff0c;需要统计某公司员工的工资情况&#xff0c;首先需要声明100个变量来分别记每个员工的工资&#xff0c;那么如果按照之前的做法&#xff0c;可能定义的结构如下所示&#xff1a; int a1,a2,a3,......a100; 要求你输出这100个员工…

JavaWeb学习|JSTL表达式

1.什么是JSTL表达式&#xff1f; JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义许多标签&#xff0c;可以供我们使用&#xff0c;标签的功能和Java代码一样 在JSP页面文件中使用JSTL表达式&#xff0c;首先需要引入核心标签库 同时&#xff0c;也要把JSTL的jar包在to…

C指针:程序员的神奇箭头,穿越内存的冒险之旅!

目录 &#x1f575;️‍♂️ 引言&#xff1a;指针&#xff0c;那些指向星星的小箭头&#xff01; 一、&#x1f3af; 探索箭头&#xff1a;指针的基础知识 1.1 指针是什么&#xff1f; 1.2 解引用操作符&#xff1a;* 是关键 1.3 指针的比较和运算 1.4 空指针&#xff1a…

深度使用苹果M1 Mac电脑一个月后的发现与问题解决

自从苹果推出M1芯片的Mac电脑后&#xff0c;其强大的性能和高效的能耗管理引起了广泛关注。许多人纷纷购买了这款新一代的Mac电脑&#xff0c;并深度使用了一个月。然而&#xff0c;在长时间使用的过程中&#xff0c;一些问题也逐渐浮现出来。本文将分享在深度使用苹果M1 Mac电…

初始C语言——详细讲解操作符以及操作符的易错点

系列文章目录 第一章 “C“浒传——初识C语言&#xff08;更适合初学者体质哦&#xff01;&#xff09; 第二章 详细认识分支语句和循环语句以及他们的易错点 第三章 初阶C语言——特别详细地介绍函数 第四章 初始C语言——详细地讲解数组的内容以及易错点 第五章 初始C语言—…

20230809在WIN10下使用python3批量将TXT文件转换为SRT文件

20230809在WIN10下使用python3批量将TXT文件转换为SRT文件 2023/8/9 17:30 由于喜欢看纪录片等外文视频&#xff0c;通过剪映/PR2023/AUTOSUB识别字幕之后&#xff0c;可以通过google翻译识别为简体中文的DOCX文档。 DOCX文档转换为TXT文档之后&#xff0c;还需要转换为SRT文档…

CentOS7安装MySQL8(RPM方式)

第一步&#xff1a;解压 tar -xvf mysql-8.0.34-1.el7.x86_64.rpm-bundle.tar -C /usr/local/java/mysql 第二步&#xff1a;按顺序安装rpm包 # rpm -ivh mysql-community-common-8.0.34-1.el7.x86_64.rpm# rpm -ivh mysql-community-client-plugins-8.0.34-1.el7.x86_64.rpm…

【PythonRS】植被显示增强(多光谱、正射、照片等)

很多时候我们需要某个区域的正射图&#xff0c;虽然正射图一般都运用了匀色的算法&#xff0c;整体色彩比较均衡。但如果研究区内有大量的植被&#xff0c;这个时候植被突出显示就很有必要了。所以今天给大家分享一下使用Python对多光谱、正射影像进行植被显示增强的算法。 一、…

【学习FreeRTOS】第2章——FreeRTOS基础知识

1.任务调度 1.1.任务调度简介 调度器就是使用相关的调度算法来决定当前需要执行的哪个任务FreeRTOS 一共支持三种任务调度方式&#xff1a; 抢占式调度&#xff1a;针对优先级不同的任务&#xff0c;每个任务都有一个优先级&#xff0c;优先级高的任务可以抢占优先级低的任务…