C++ 类与对象入门:基础知识与定义

引言:

  本来打算用一篇介绍清楚C++中的类与对象,再三考虑后觉得不妥:第一,知识点实在太多;第二,对于从刚学完C并打算过渡到C++的朋友来说,学的太深较有难度…

  总而言之,我打算用三到四篇文章去介绍,难度由易到难,希望可以帮助各位能全面且无压力的学习该内容
  本文也会不断的更新,比如加入一些图片或者动图来帮助大家理解,如有好想法希望各位能够多多批评指正

第一部分:类的基本概念

类的定义

  在C++中,类是一种用户自定义的数据类型(类似于C语言中的struct),它将数据(属性)和操作这些数据的函数(方法)封装在一起。

  类是面向对象编程的核心概念之一,它允许我们以一种结构化的方式组织代码,提高代码的可重用性可维护性

定义一个类

类的定义通常包含以下几个部分:

  1. 类名:类的名字应该具有描述性,以便其他开发者能够理解该类的用途。
  2. 成员变量:类内部的数据,也称为属性。
  3. 成员函数:类内部的函数,用于操作成员变量。

对比C语言来看,"内容"不过多了一个成员函数(但是大有讲头)

下面是一个简单的类定义示例:

#include <iostream>
using namespace std;class Person {// 成员变量string name;int age;public:// 成员函数void setName(string n) {name = n;}void setAge(int a) {age = a;}void display() {cout << "Name: " << name << ", Age: " << age << endl;}
};int main() {Person p;p.setName("Alice");p.setAge(30);p.display();return 0;
}

在这个例子中:依旧是经典的Person类

  • Person 是类名。
  • nameage 是成员变量。
  • setNamesetAgedisplay 是成员函数。

访问控制

C++ 中提供了三种访问控制关键字:publicprivateprotected。这些关键字用于控制类成员的可见性和可访问性。

  1. public:公共成员,可以在类的外部直接访问。
  2. private:私有成员,只能在类的内部访问。
  3. protected:受保护成员,只能在类的内部和派生类中访问。

访问控制示例

#include <iostream>
using namespace std;class Person {
private:string _name;int _age;public:void setName(string n) {_name = n;}void setAge(int a) {_age = a;}void display() {cout << "Name: " << _name << ", Age: " << _age << endl;}
};int main() {Person p;p.setName("李四");p.setAge(18);p.display();// 下面这行代码会编译错误,因为 _name 是私有的// p._name = "王五";return 0;
}

在这个例子中,_name_age 被声明为 private,因此不能在类的外部直接访问它们。只有通过 setNamesetAge 这样的公共成员函数才能修改这些私有成员。

💡tips:建议各位在声明私有变量时在前方加入符号’_’

类域

  类定义了一个作用域,类内的所有成员都在类的作用域;若在类外定义成员函数,需加入::此时将不再是内联函数(inline,详细见历史文章)
  类影响的是编译的规则,如果不加person::,则默认全局查找,加入就会告知编译profession函数是person类的成员函数

void person::profession()
{cout << "类外定义"<<endl;
}

类的实例化

可理解为图纸 -> 实物class_type -> obj)的过程

person p1;

用person实例化出一个对象,person充当图纸,实物充当实物。

类对象的大小

在文章开头提到 C++classCstruct类似,各位也能感受出来。

class中成员变量也是需要对齐的,法则与结构体一致

各位可以注意到,class中有成员函数的存在,也需要对齐吗,如果这样每个对象都需要开出这么多空间吗?我们可以创建两个变量,然后对比两者成员函数的地址

在这里插入图片描述
显而易见,两对象的成员函数地址一致,该类的成员函数共用一块内存


在这里插入图片描述

构造函数与析构函数

构造函数和析构函数是特殊的成员函数,它们分别在对象创建和销毁时自动调用。

名称作用
构造函数用于初始化对象。构造函数的名称与类名相同,且没有返回值类型。
析构函数用于清理对象占用的资源。析构函数的名称与类名相同,但在前面加上波浪线 ~,且没有参数和返回值类型

声明

  • 在类名前加~
  • 无参数无返回值
  • 一个类只能有一个析构函数若未显式定义,则由系统默认生成
  • 对象生命周期结束时,编译器自动调用析构函数
  • 跟构造函数相似,对内置类型不做处理,自定义类型会调用其析构函数
  • 我们显示编写析构函数,自定义类型被销毁时一样会调用析构函数
~person(){delete[] _name;free(this->ps);ps = nullptr;}

如果该类有其他类的对象会怎样呢?

#include <iostream>
using namespace std;class Test {
private:int socre;
public:Test(int score=0){}~Test() {cout << "Test析构函数" << endl;}
};class Person {
private:string _name;int _age;Test _t1;public:void setName(string n) {_name = n;}void setAge(int a) {_age = a;}void display() {cout << "Name: " << _name << ", Age: " << _age << endl;}~Person() {cout << "Person类析构函数" << endl;}
};int main() {Person p;return 0;
}
Person类析构函数
Test析构函数

运行结果如上,在 C++ 中,对象的析构顺序与其构造顺序相反。具体来说:

构造顺序先构造 Person 对象 p。在构造 Person 对象时,会构造其成员对象 _t1
析构顺序当 Person 对象 p 的生命周期结束时,先调用 Person 类的析构函数 ~Person()。在 Person 类的析构函数中,会销毁其成员对象 _t1,因此调用 Test 类的析构函数 ~Test()。

因此,Person 类的析构函数先调用,然后才是 Test 类的析构函数。这是因为 Person 对象的整体生命周期结束后,才会销毁其成员对象。

拷贝构造函数
  • 拷贝构造函数是构造函数的一种重载

  • 拷贝构造函数的参数必须是类型对象的引用传值方式会导致无穷递归调用

  • 自定义类型对象进行拷贝时必须调用拷贝构造函数,因此传值传参和传值返回都会调用拷贝构造。

  • 若未显式定义拷贝构造函数,编译器会生成一个默认的拷贝构造函数

  • 对内置类型成员变量进行浅拷贝对自定义类型成员变量调用其拷贝构造函数

  • 如果一个类显式实现了析构函数并释放资源,那么也需要显式实现拷贝构造函数。

  • 传值返回会产生临时对象并调用拷贝构造函数,而传引用返回不会产生拷贝,但要确保返回的对象在函数结束后仍然有效,否则会返回野引用。传引用可以减少不必要的拷贝,但要确保引用的有效性。

对于第二条各位可能不太好理解,假如我们这么定义

//以下为错误示范,请勿模仿
Person(Person source) { _name = source._name; _age = source._age;
}
//.....
int main(){Person p1("张三","18");Person p2(p1);
}

由于是传值操作,相当于把p1拷贝了一份并且该变量也是个Person类对象,也需要借助拷贝构造进行拷贝,因此会造成无限递归,十分危险
在这里插入图片描述
正确示范

class Person {
private:string _name;int _age;public:// 默认构造函数Person(_name = nullptr,_age = 0) :{}// 拷贝构造函数Person(const Person& other) {strcpy(_name,name);_age = age;}void setName(string n) {_name = n;}void setAge(int a) {_age = a;}void display() {cout << "Name: " << name << ", Age: " << age << endl;}
};int main() {Person p1;p1.setName("张三");p1.setAge(18);Person p2(p1);  // 调用拷贝构造函数p2.display();return 0;
}

在这个例子中,_name 是一个动态分配的字符串指针。析构函数负责释放 _name 指向的内存,防止内存泄漏。
默认析构函数不会进行delete (free) 操作,需要手动释放内存

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

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

相关文章

一篇文章总结 SQL 基础知识点

1. 官方文档 MySQL&#xff1a;https://dev.mysql.com/doc/refman/8.4/en/ SQL Server&#xff1a;What is SQL Server? - SQL Server | Microsoft Learn Oracle&#xff1a;https://docs.oracle.com/en/database/oracle/oracle-database/23/lnpls/loe.html 2. 术语 SQL S…

电脑程序变化监控怎么设置?实时监控电脑程序变化的五大方法,手把手教会你!

​在现代办公和信息安全领域&#xff0c;实时监控电脑程序变化是一项至关重要的任务。 无论是企业内网安全、员工行为审计&#xff0c;还是个人电脑的隐私保护&#xff0c;了解并设置有效的监控方法都是必不可少的。 本文将详细介绍五种电脑程序变化监控的方法&#xff0c;帮助…

️ Vulnhuntr:利用大型语言模型(LLM)进行零样本漏洞发现的工具

在网络安全领域&#xff0c;漏洞的发现和修复是保护系统安全的关键。今天&#xff0c;我要向大家介绍一款创新的工具——Vulnhuntr&#xff0c;这是一款利用大型语言模型&#xff08;LLM&#xff09;进行零样本漏洞发现的工具&#xff0c;能够自动分析代码&#xff0c;检测远程…

SAP-ABAP开发学习-FUNCTION ALV

ALV概览 ALV全称SAP List View&#xff0c;是SAP提供的一个强大的数据报表显示工具。ALV实质上是一个屏幕控件对象&#xff0c;它通过程序传递数据内表的方式来显示数据。 实现方式&#xff1a;调用标准函数&#xff1b;优化接口:用户可以实现对字段的排序、筛选及统计等功能。…

51c嵌入式~IO合集1

我自己的原文哦~ https://blog.51cto.com/whaosoft/12383193 一、单片机通信数据接收解析方法 前阵子一朋友使用单片机与某外设进行通信时&#xff0c;外设返回的是一堆格式如下的数据&#xff1a; AA AA 04 80 02 00 02 7B AA AA 04 80 02 00 08 75 AA AA 04 80 02 00 9B E2…

layaair给图片精灵绘制形状并添加点击事件注意点击的区域不是方块

默认的图片添加进来都是方块&#xff0c;哪怕是圆形的图片&#xff0c;点击也是方块区域如下图&#xff0c;这个圆的上下左右方向角的位置都可点击。 利用sprite的Graphics属性则可以编制线条&#xff0c;圆形等形状。如下图 但是点击的区域还是默认根据sprite的高宽来设定的。…

vite 创建了一个项目后,如何实现工程化

当我们使用 vite 创建了一个项目后&#xff0c;要开发自己的东西。首先要做的就是先将开发文件变成自己的样子。 这是一个刚刚创建项目的文件夹及展示 开始整改文件夹 修改文件 main.ts不需要修改App.vue删除无用的内容 <template><div>app组件</div> &l…

推荐一款好用的redis管理工具TinyRDM

简述 对于经常要操作redis的人员来说&#xff0c;一款好用开源的redis可视化管理工具可以事半功倍&#xff0c;今天要介绍的TinyRDM就是这样的工具&#xff0c;支持多端&#xff08;MAC/Window/Linux&#xff09;&#xff0c;并且是开源的。 github地址&#xff1a;https://git…

CSPM(项目管理专业人员评价)证书还不如PMP?垃圾证书……

一、什么是CSPM CSPM&#xff08;China Standards Project Management&#xff09;是指依据中国标准开展的项目管理专业人员能力评价。它是由中国标准化协会&#xff08;全国项目管理标准化技术委员会秘书处&#xff09;设立&#xff0c;运用已发布的项目管理国家标准&#xf…

平衡相图在资源可持续利用方向的应用

平衡相图是描述物质在特定温度、压力和组成条件下达到相平衡状态的图表。在环境科学中&#xff0c;平衡相图可以用于预测和解释自然环境中物质的分布、迁移和转化过程&#xff0c;对于资源的可持续利用和环境污染的防治具有重要意义。 平衡相图在资源的可持续利用方向的应用主…

【YOLOv11[基础]】目标对象模糊处理

目录 一 安装YOLOv11 二 实践 使用Ultralytics YOLO11进行目标对象模糊处理,包括对图像或视频中特定检测到的对象应用模糊效果。这可以使用YOLO11模型功能来识别和操作给定场景中的对象。 目标对象模糊处理的优点: 隐私保护

Day16-非关系型数据库服务-redis

Day16-非关系型数据库服务-redis 1、非关系型数据库服务Redis1.1 Redis服务概述介绍1.1.1 缓存服务介绍1.1.2 缓存服务产品介绍1.1.3 缓存服务应用场景 1.2 Redis服务安装部署1.2.1 缓存服务安装部署 1.3 Redis服务基础管理操作1.3.1 缓存服务配置文件介绍1.3.2 缓存服务安全配…

如何对pdf文件进行加密?pdf文件加密全攻略与深度解析(5个方法)

如何对pdf文件进行加密&#xff1f; 只见&#xff0c;在深夜的情报局里&#xff0c;特工小李将一份绝密PDF文件放在保险箱内&#xff0c;以为这样就天衣无缝了。 细细推敲&#xff0c;漏洞百出&#xff1a; 如果钥匙被盗呢&#xff1f;如果被神匠破解出密码呢&#xff1f;如果…

解析MES管理系统在企业中的应用策略

在智能制造浪潮汹涌的今天&#xff0c;MES管理系统成为了连接生产现场与管理决策层的关键桥梁&#xff0c;其重要性在企业的智能化转型中愈发凸显。面对智能制造时代的新挑战&#xff0c;如何充分利用MES管理系统的优势&#xff0c;实现生产流程的智能、高效与透明&#xff0c;…

Pytest中autouse参数的用法

引言 在Pytest中&#xff0c;Fixture是一种非常有用的功能&#xff0c;它允许我们在测试前后进行一些设置和清理工作。通常&#xff0c;我们会在测试函数中显式地声明需要使用的Fixture。然而&#xff0c;有时候我们希望某些Fixture在所有测试中自动应用&#xff0c;而不需要在…

循序渐进丨openGauss / MogDB 数据库内存占用相关SQL

一、内存总体分布 数据库总体内存使用分布 select * from gs_total_memory_detail; 当dynamic_used_memory大于max_dynamic_memory就会报内存不足&#xff1b;如果此时dynamic_used_memory小于max_dynamic_memory&#xff0c;而dynamic_peak_memory大于max_dynamic_memory表…

机房巡检机器人有哪些功能和作用

随着数据量的爆炸式增长和业务的不断拓展&#xff0c;数据中心面临诸多挑战。一方面&#xff0c;设备数量庞大且复杂&#xff0c;数据中心内服务器、存储设备、网络设备等遍布&#xff0c;这些设备需时刻保持良好运行状态&#xff0c;因为任何一个环节出现问题都可能带来严重后…

2024护理类科技核心期刊汇总(最新版)

2024年9月中国科技核心期刊目录&#xff08;2024年版&#xff09;正式公布&#xff0c;13本护理类期刊入选。常笑医学整理了这13本护理类科技核心期刊的详细参数&#xff0c;以及投稿经验&#xff0c;供大家在论文投稿时参考&#xff0c;有需要的赶紧收藏&#xff01; 1.《中华…

基于Springboot+Vue的物流系统 (含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 该系统…

AI创作者与人类创作者的协作模式

公主请阅 1. AI创作者的崛起1.1 AI创作者的工作原理1.2 AI创作者的优势 2. 人类创作者的独特价值2.1 创造性与情感2.2 伦理与价值观2.3 文化与背景 3. AI与人类的协作模式3.1 协同创作3.2 内容编辑3.3 数据驱动的创作3.4 跨媒体协作 4. AI与人类协作的挑战4.1 技术局限性4.2 版…