【c++】类和对象详解

✅博客主页:爆打维c-CSDN博客​​​​​​ 🐾

🔹分享c语言知识及代码

来都来了! 点个赞给博主个支持再走吧~!


一.类的定义

(1)类定义格式

class为类定义的关键字,定义一个类格式如下:

class 类名{//代码块(类的主体)};  //注意分号不能省略

需要注意的是:

1.类体中的内容称为类的成员,类中的变量称为类的成员变量,类中的函数为类的成员函数 

2.为了区分成员变量,我们常在成员变量前加一个 _ ,以此来区分,例如我们创造一个日期类Date,其中有年月日三个成员,那么我们可以这样定义:

class Date{public://成员函数代码块...
private:int _year;int _month;int _day;};

3.C++中也可以用struct定义类,C++兼容C,明显的变化是struct里面也能定义函数,不过我们这里还是推荐用class定义类

4.定义在类里的成员函数默认为内联函数inline

(2)访问限定符

1.通过访问限定符实现封装

C++⼀种实现封装的方式,⽤类将对象的属性与方法结合在⼀块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用

2.public protected private的区别

其实就字面意思上来看,已经体现出它们的特点了:

• public公有的,protected保护的,private私有的

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

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

protected和private是⼀样的,以后继承章节才能体现出他们的区别

• class定义成员没有被访问限定符修饰时默认为private,struct默认为public。
• ⼀般成员变量都会被限制为private/protected,需要给别⼈使⽤的成员函数会放为public。

(3)类域

  • 类定义了⼀个新的作用域,类的所有成员都在类的作用域中,在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域。
  • 类域影响的是编译的查找规则让程序能找到类中的声明的函数或成员变量

二.实例化对象

就像我们想要一个整型变量a,那么int a=...,类是对象进行⼀种抽象描述,是⼀个模型⼀样的东西,限定了类有哪些成员变量,这些成员变量只是声明,没有分配空间,用类实例化出对象时,才会分配空间。

类实例化出的每个对象,都有独立的数据空间,那么它们的大小是多少呢?

它们的存储符合以下规则,成员函数是不存储到每个具体对象里的,它们被放在公共代码区

C++规定类实例化的对象要符合内存对齐的规则

不懂内存对齐规则的小伙伴可以看看我的这篇文章【C语言】结构体内存对齐_c struct 内存对齐-CSDN博客


三.this指针

1. 编译器编译后,类的成员函数默认都会在形参第一个位置,增加⼀个当前类类型的指针,

叫做this指针

比如Date类的Add的真实原型为, void Add(Date* const this, const Date& d2);

2. 类的成员函数中访问成员变量,本质都是通过this指针访问的,

    如Init函数中给_year赋值, this->_year = year;

3 .注意: C++规定不能在实参和形参的位置显示的写this指针(编译时编译器会处理),但是可以在函数体内显示使用this指针。

4. this指针存在内存的栈区


四.类的默认成员函数

(1)类的默认成员函数有6个,我们不写的情况下编译器会默认生成6个成员函数(但不一定能实现我们需要的功能)所以为了实现具体的功能,我们需要根据要求写出部分成员函数。

下面我们来介绍前四种比较重要的成员函数(后两个取地址基本不需要我们自己实现,编译器生成的已经够用):

重点来了!!!!

1.构造函数

构造函数是特殊的成员函数,构造函数虽然叫构造,但是构造函数的主要任务并不是开空间创建对象(我们常使用的局部对象是栈帧创建时,空间就开好了),而是对象实例化时初始化对象构造函数的本质是要替代我们以前Stack和Date类中写的Init函数的功能,构造函数自动调用的特点就完美的替代的了Init。

🔶构造函数的特点:

  • 函数名与类名相同
  • ⽆返回值 (返回值啥都不需要给,也不需要写void,C++规定)
  • 对象实例化时系统会自动动调用对应的构造函数。
  • 构造函数可以重载。
  • 如果类中没有显式定义构造函数,则C++编译器会⾃动生成⼀个⽆参的默认构造函数,⼀旦显式定义编译器将不再⽣成。
  • 无参构造函数、全缺省构造函数、我们不写构造时编译器默认生成的构造函数,都叫做默认构造函数。但是这三个函数有且只有⼀个存在,不能同时存在。⽆参构造函数和全缺省构造函数虽然构成函数重载,但是调用时会存在歧义。要注意⽆参构造函数、全缺省构造函数也是默认构造,总结⼀下就是不传实参就可以调用的构造就叫默认构造

大家可以看看下面这个Date类的定义,就明白不同构造函数的特点了

class Date {public:
// 1.⽆参构造函数Date() {_year = 1;_month = 1;_day = 1;}
// 2.带参构造函数Date(int year, int month, int day) {_year = year;_month = month;_day = day;}
// 3.全缺省构造函数/*Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}*/private:int _year;int _month;int _day;
};

2.析构函数

析构函数与构造函数功能相反,析构函数不是完成对对象本⾝的销毁,⽐如局部对象是存在栈帧的,函数结束栈帧销毁,他就释放了,不需要我们管,C++规定对象在销毁时会⾃动调⽤析构函数,完成对象中资源的清理释放工作。

🔶析构函数的特点:

  • 析构函数名是在类名前加上字符 ~
  • ⽆参数⽆返回值。 (这⾥跟构造类似,也不需要加void)
  • ⼀个类只能有⼀个析构函数。若未显式定义,系统会⾃动⽣成默认的析构函数。
  • 对象⽣命周期结束时,系统会⾃动调⽤析构函数。
  • 跟构造函数类似,我们不写编译器⾃动⽣成的析构函数对内置类型成员不做处理,⾃定类型成员会调⽤他的析构函数。
  • ⾃定义类型成员⽆论什么情况都会⾃动调⽤析构函数,跟我们自己写不写无关。
  • ⼀个局部域的多个对象,C++规定后定义的先析构

像我们上面写的Date类没有资源需要释放,那么就不需要写析构函数。

3.拷贝构造

构造函数的第⼀个参数是⾃⾝类类型的引⽤且任何额外的参数都有默认值,那么此构造函数也叫做拷⻉构造函数,拷⻉构造是⼀个特殊的构造函数。

  • 🔶拷⻉构造的特点:
  • 拷⻉构造函数是构造函数的⼀个重载
  • 拷⻉构造函数的参数只有⼀个且必须是类类型对象的引用,使⽤传值⽅式编译器直接报错,因为语法逻辑上会引发⽆穷递归调⽤。
  • C++规定⾃定义类型对象进行拷贝行为必须调用拷贝构造,所以这⾥⾃定义类型传值传参和传值返回都会调⽤拷⻉构造完成。
  • 若未显式定义拷贝构造,编译器会自动生成拷贝构造函数。⾃动⽣成的拷⻉构造对内置类型成员变量会完成值拷⻉/浅拷⻉(⼀个字节⼀个字节的拷⻉),对⾃定义类型成员变量会调⽤他的拷⻉构造。
  • 传值返回会产生一个临时对象调用拷贝构造,传值引用返回,返回的是返回对象的别名(引用),没有产生拷贝。但是如果返回对象是⼀个当前函数局部域的局部对象,函数结束就销毁了,那么使⽤引⽤返回是有问题的,这时的引⽤相当于⼀个野引⽤,类似⼀个野指针⼀样。传引用返回可以减少拷贝,但是一定要确保返回对象,在当前函数结束后还在,才能⽤引⽤返回。

下面实现的是对Date类的拷贝构造函数

Date::Date(const Date& d) {_year = d._year;_month = d._month;_day = d._day;
}

对深拷贝浅拷贝不懂的同学可以去看我的这篇文章

深拷贝与浅拷贝-CSDN博客

4.赋值重载

赋值重载很容易跟拷贝构造弄混淆,大家一定要注意区分!

二者的区别在于,拷贝构造是给一个未初始化的对象初始化,拷⻉构造⽤于⼀个对象拷⻉初始化给另⼀个要创建的对象。而赋值重载是这两个对象均存在且已经初始化,把其中一个的值赋给另外一个!

🔶赋值运算符重载的特点:

  1. 赋值运算符重载是⼀个运算符重载,规定必须重载为成员函数。赋值运算重载的参数建议写成const当前类类型引⽤,否则会传值传参会有拷⻉
  2. 有返回值,且建议写成当前类类型引⽤,引⽤返回可以提⾼效率,有返回值⽬的是为了⽀持连续赋值场景
  3. 没有显式实现时,编译器会⾃动⽣成⼀个默认赋值运算符重载,默认赋值运算符重载⾏为跟默认构造函数类似,对内置类型成员变量会完成值拷⻉/浅拷⻉(⼀个字节⼀个字节的拷⻉),对⾃定义类型成员变量会调⽤他的拷⻉构造。
  4. 像Date这样的类成员变量全是内置类型且没有指向什么资源,编译器⾃动⽣成的赋值运算符重载就可以完成需要的拷⻉,所以不需要我们显⽰实现赋值运算符重载。当编译器⾃动⽣成的赋值运算符重载完成的值拷⻉/浅拷⻉不符合我们的需求时,需要我们自己实现深拷贝(对指向的资源也进行拷贝)。小技巧:如果⼀个类显⽰实现了析构并释放资源,那么他就需要显⽰写赋值运算符重载,否则就不需要。

下面给出Date类的赋值重载代码

/ 赋值运算符重载
// d2 = d3    d2.operator=(&d3)
Date& Date::operator=(const Date& d){_year = d._year;_month = d._month;_day = d._day;return *this;  //返回d2
}

如果这篇文章对你有帮助的话,请给博主一个免费的赞鼓励一下吧~ 💓

本文仅简单介绍了有关类和对象的一些基本概念和相关代码实现,以上个人拙见,若有错误之处,希望各位能提出宝贵的建议和更正,感谢您的观看!

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

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

相关文章

turtle.circle() 函数绘制弧形规律助记图 ← Python

【Python 之 turtle.circle() 函数定义】 定义:turtle.circle(radius, extent)作用:根据半径 radius 绘制 extent 角度的弧形参数:radius :弧形半径当 radius 值为正数时,圆心在当前位置/小海龟左侧。当 radius 值为负…

9月美联储决策前哨战——美国CPI数据来袭

随着本周关键CPI数据的即将发布,市场正翘首以待,这将是美联储在9月17日至18日议息会议前获取的最后一块重要经济拼图。鉴于美联储官员已进入传统的政策静默期,8月份的CPI报告无疑将成为交易员们评估未来货币政策走向的重要标尺。 欧洲央行降…

16. MyBatis的延迟加载机制是什么?如何配置?有哪些优缺点?

延迟加载(Lazy Loading)是MyBatis提供的一种机制,用于优化数据库查询性能。在启用延迟加载时,某些关联对象或集合只有在被实际访问时才会触发数据库查询,而不是在主对象加载时立即加载。这种机制可以减少不必要的数据库…

Logstash 配置Java日志格式的方法

Logstash 是用于日志收集的开源工具,通常与 Elasticsearch 和 Kibana 一起使用,形成 ELK Stack(现在称为 Elastic Stack)。Logstash 非常灵活,可以通过配置文件(通常是 .conf 文件)来定义数据的…

AI模型:追求全能还是专精?-- 之5 “机器人”最终会成为“人类”的主导者吗?--答案是:不会!

Q1、先回顾一下:我们正在设计的是 一个变形机器人(变形金刚Transformers)。它是作为三种机器人(移动机器人Robot、代理机器人Agent和人形机器人Android )的共同原型(可以视为“祖先”--上述三者的祖传代码&…

[000-01-002].第03节:Git基础命令

我的博客大纲 我的GIT学习大纲 1、Git的常用命令 2、Git操作步骤: 2.1.操作Git第一步:设置全局的用户签名 1.设置用户名: 格式:git config --global user.name 用户名命令:git config --global user.name root 2.设置…

Taro + Vue 的 CSS Module 解决方案

一、开启模块化配置 Taro 中内置了 CSS Modules 的支持,但默认是关闭的。如果需要开启使用,请先在编译配置中添加如下配置: weapp: {module: {postcss: {// css modules 功能开关与相关配置cssModules: {enable: true, // 默认为 false&…

vue3中动态引入本地图片的两种方法

方法一 <img width"10" height"10":src"/src/assets/nncs2/jiantou${index 1}.png" alt"" /> 推荐 简单好用 方法二 const getImg index > {const modules import.meta.glob(/assets/nncs2/**/*.{png,svg,jpg,jpeg}, { …

如何解决户用光伏项目管理难题?

户用光伏作为分布式能源的重要组成部分&#xff0c;正迎来前所未有的发展机遇。户用光伏项目的复杂性和多样性也给项目管理带来了诸多挑战&#xff0c;包括客户分散、安装周期长、运维难度大、数据监控不及时等问题。为解决这些难题&#xff0c;构建一套高效、智能的户用光伏业…

SpringMVC基于注解使用:国际化

01-国际化介绍 首先在bootstrap下载个页面 下载后把登录页面的代码粘上去 然后再登录页面代码上有些超链接需要再spring-mvc.xml里面配置下&#xff0c;登录页面才能正常显示 配置静态资源 国际化-根据浏览器语言国际化 现在是中文的情况&#xff0c;要改为英文 1.配置下属…

【网络】DNS

definition DNS&#xff08;Domain Name System&#xff0c;域名系统&#xff09;服务器是互联网上的重要基础设施之一&#xff0c;它的主要作用是将人们易于记忆的域名&#xff08;如www.example.com&#xff09;转换成计算机可以直接识别的IP地址&#xff08;如192.0.2.1&am…

OFDM信号PARP的CCDF图

文章目录 引言代码代码疑难解答参考文献 引言 本书主要参考了文献1&#xff0c;但实际上该书中符号和表述的错误非常多&#xff08;只能说棒子是这样的&#xff09;&#xff1b;同时因为发表时间的关系&#xff0c;很多MATLAB代码进行了更新&#xff0c;原书提供的代码已经无法…

Flutter中自定义气泡框效果的实现

在用户界面的设计中&#xff0c;气泡框&#xff08;Bubble&#xff09;是一种非常有效的视觉工具&#xff0c;它可以用来突出显示信息或提示用户。气泡框广泛应用于聊天应用、通知提示等场景。在 Flutter 中&#xff0c;虽然有很多现成的气泡框组件&#xff0c;但如果你想要更多…

使用豆包MarsCode 编写 Node.js 全栈应用开发实践

以下是「豆包MarsCode 体验官」优秀文章&#xff0c;作者狼叔。 欢迎更多用户使用豆包MarsCode 并分享您的产品使用心得及反馈、创意项目开发等&#xff0c;【有奖征集&#xff5c;人人都是豆包MarsCode 测评官&#xff01;】活动正在火热进行中&#xff0c;欢迎大家投稿参加&a…

跨部门SOP与统一知识库:打破信息孤岛,促进团队协作

引言&#xff1a; 在当今这个快速变化且高度竞争的商业环境中&#xff0c;企业面临着前所未有的挑战&#xff0c;其中之一便是如何高效地跨越部门界限&#xff0c;实现无缝协作。传统的组织结构往往导致信息孤岛的出现&#xff0c;不同部门间流程不一致、信息不共享&#xff0…

openvas、gvmd、aide、ossec、clamav这些软件的用途

这些软件都是用于网络和系统安全的工具&#xff0c;各自有不同的用途&#xff1a; OpenVAS: OpenVAS&#xff08;Open Vulnerability Assessment System&#xff09;是一个开源的漏洞扫描工具。它用于扫描系统和网络中的安全漏洞&#xff0c;识别潜在的安全风险&#xff0c;并提…

Java中HashMap 和 ConcurrentHashMap

HashMap 和 ConcurrentHashMap 都是 Java 中用来存储键值对的集合类&#xff0c;但它们有不同的设计目标&#xff0c;适用于不同的场景。以下是它们的详细对比和介绍。 ### 1. HashMap 概述 HashMap 是基于哈希表的非同步集合类&#xff0c;主要用于在单线程环境下存储键值对。…

【车载开发系列】ParaSoft单元测试环境配置(一)

【车载开发系列】ParaSoft单元测试环境配置(一) ParaSoft单元测试环境配置 【车载开发系列】ParaSoft单元测试环境配置(一)一. 什么是bdf文件二. bdf文件构成三. 新规做成bdf文件四. 导入bdf文件创建测试工程五. 获取编译器信息六. 新增自定义编译器Step1:打开向导Step2:…

C和指针:标准函数库

整型函数 算术 <stdlib.h> int abs( int value); long int labs( long int value ); div_t div( int numerator, int denominator ); ldiv_t ldiv( long int numer,long int denom); abs 函数返回它的参数的绝对值. div 函数把它的第2个参数(分母)除以第1个参数(分子…

JAVA一键下单新鲜到家同城生鲜物流系统小程序源码

一键下单&#xff0c;新鲜到家 —— 探索同城生鲜物流系统的魅力 &#x1f69a; 一键下单&#xff0c;轻松享受便捷生活 在这个快节奏的时代&#xff0c;谁不想在忙碌之余还能轻松享受美食呢&#xff1f;&#x1f60b; "一键下单新鲜到家"的同城生鲜物流系统&#…