【C++】类和对象(四)

前言:在类和对象中,我们走过了十分漫长的道路,今天我们将进一步学习类和对象,类和对象这块荆棘地很长,各位一起加油呀。

💖 博主CSDN主页:卫卫卫的个人主页 💞
👉 专栏分类:高质量C++学习 👈
💯代码仓库:卫卫周大胖的学习日记💫
💪关注博主和博主一起学习!一起努力!
在这里插入图片描述


目录标题

  • 类和对象
    • const修饰成员函数
    • 再谈构造函数之函数体赋值
    • explict关键字
    • static成员


类和对象

const修饰成员函数

在C++中,可以使用const关键字来修饰成员函数。const修饰符可以被应用于类的成员函数,这表示该函数不会修改任何类的成员变量。

当一个成员函数被const修饰时,它被称为常量成员函数。常量成员函数承诺不会修改任何成员变量。常量成员函数的定义和声明都必须包含const关键字。
语法格式

返回类型 类名::函数名()const
{//函数体......
}

下面是一个示例

class MyClass 
{
public:void nonConstFunction(int year,int month ,int day); // 非常量成员函数             void nonConstFunction() const;  // 常量成员函数
private:int _day;int _month;int _year;
};void MyClass::nonConstFunction(int year = 1,int month = 1 ,int day =1) 
{// 对成员变量进行修改_year = year;_month = month;_day = day;
}void MyClass::nonConstFunction() const 
{// 不对成员变量进行修改cout << "year: " << _year << " month: " << _month << " day: " << _day << endl;
}

在上面的示例中,nonConstFunction是一个非常量成员函数,可以修改成员变量。而nonConstFunction的const版本是一个常量成员函数,不会修改成员变量。

那我们思考一下为什么在上面这个示例中,const修饰了以后就无法对里面的成员变量进行修改了?请看下图:
在这里插入图片描述

在上图中我们可以知道,编译器会对this指针加上const进行修饰,让外部变量无法对其修改

如果在上面式子中我们对const修饰的成员函数中的成员变量进行修改,就会出现如下情况,如下所示:
在这里插入图片描述
使用const修饰常量成员函数的好处是可以在常量对象上调用该函数,而不会导致编译错误。这样可以提高代码的可读性和安全性。


注意事项:
C++中const成员函数有以下限制:

  1. const成员函数不能修改类的非静态数据成员。这是因为const成员函数保证不会修改对象的状态,所以不能修改任何非静态数据成员。

  2. const成员函数只能调用其他const成员函数。这是因为const成员函数保证不会修改对象的状态,所以只能调用其他也不会修改对象状态的const成员函数。

  3. const成员函数不能通过指针或引用返回非const指针或引用。这是因为const成员函数要保证不会修改对象的状态,所以不能返回非const指针或引用,否则调用者就可以通过这个指针或引用修改对象的状态。

  4. const成员函数可以被非const对象和const对象调用。非const对象调用const成员函数时会被自动转换为const对象。

  5. const成员函数不能被声明为虚函数。虚函数是根据对象的动态类型来调用的,而const成员函数是根据对象的静态类型来调用的,所以不能将const成员函数声明为虚函数。


再谈构造函数之函数体赋值

在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。

class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};

虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值

  • . 初始化列表:构造函数可以通过初始化列表来初始化成员变量。在构造函数的参数列表后面使用冒号(:)来定义初始化列表,然后通过成员变量名称和初始值来初始化成员变量(当然这个括号里面也可以写一个有返回值的表达式)。例如:
    在这里插入图片描述
    在这里插入图片描述

注意:

  1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
  2. 类中包含以下成员,必须放在初始化列表位置进行初始化:
    引用成员变量,const成员变量,自定义类型成员(该类没有默认构造函数)

实例演示

class A
{
public:A(int a):_a(a){cout <<"_a: " << _a << endl;}
private:int _a;
};class d
{
public:d(int a, int b, int c):_aa(a),_b(b),_c(c){cout << "_b: " << _b << endl;cout << "_c: " << _c << endl;}private:A _aa;//自定义变量int& _b;//引用const int _c;//const
};int main()
{d d1(10, 20, 30);return 0;
}

在这里插入图片描述

  1. 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。
  2. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关

在C++中,构造函数体赋值的注意事项如下:

  1. 初始化列表的优先级高于构造函数体内的赋值:如果同时在初始化列表和构造函数体内对成员变量进行赋值,初始化列表中的赋值操作会先于构造函数体内的赋值操作执行。

  2. 成员变量的声明顺序决定了初始化的顺序:成员变量在类中的声明顺序决定了它们初始化的顺序。在构造函数体内的赋值操作也会按照成员变量的声明顺序进行。

  3. 成员变量的初始化顺序与初始化列表中的顺序一致:在初始化列表中的顺序决定了成员变量初始化的顺序。如果在初始化列表中没有给出某个成员变量的初始值,该成员变量会按照默认构造函数进行初始化。

  4. 常量成员变量必须在初始化列表中进行初始化:对于类中的常量成员变量(const类型),它们必须在初始化列表中进行初始化,而不能在构造函数体内进行赋值操作。

  5. 使用成员初始化列表可以提高效率:使用成员初始化列表可以在对象构造时直接进行赋值操作,避免了先构造默认对象再赋值的额外开销,因此可以提高效率。

总体而言,通过初始化列表进行成员变量的赋值是更好的选择,除非有特殊需要,如需要在构造函数体内做其他逻辑处理,才使用构造函数体内的赋值语句。


explict关键字

在C++中,explicit也是一个关键字,但其使用情况与C#中的略有不同。

在C++中,explicit关键字可以用于单参数构造函数(或转换函数),以防止编译器进行隐式类型转换。默认情况下,单参数构造函数可以用于隐式类型转换。但是,当我们使用explicit关键字来修饰该构造函数时,它将变为只能进行显式类型转换的构造函数,禁止隐式转换。

下面是一个使用explicit关键字的示例:

class Number {
private:int value;
public:explicit Number(int value) : value(value) {}int getValue() const {return value;}
};void printNumber(const Number& number) {std::cout << number.getValue() << std::endl;
}int main() {int intValue = 10;// 隐式类型转换不被允许// Number number = intValue;// 显式类型转换Number number = Number(intValue);printNumber(number);return 0;
}

在这里插入图片描述

在上面的示例中,Number类定义了一个带有单参数的构造函数,并使用explicit关键字进行修饰。在main函数中,我们首先声明一个int类型的变量intValue,并将其赋值为10。然后,我们尝试使用隐式类型转换将intValue转换为Number类型,但由于Number类的构造函数使用了explicit关键字,这会导致编译错误。接着,我们使用显式类型转换将intValue转换为Number类型,并将结果赋值给number变量。最后,我们通过调用printNumber函数,将number对象传递给它并输出结果。可以看到,通过使用explicit关键字,我们可以明确指定我们希望进行显式类型转换,从而避免了隐式类型转换可能带来的意外行为。


static成员

在C++中,static关键字可以应用于类的成员,用于指示该成员是静态的。静态成员与类的实例无关,它们属于整个类而不是类的实例。以下是一些关于C++中静态成员的信息:

  1. 静态数据成员:静态数据成员与类的所有实例共享,它们只有一个副本。可以在类的内部声明并在类的外部初始化静态数据成员必须在类的定义之外进行初始化,并且必须在类的外部定义。并且静态成员变量是在初始化时分配内存的,程序结束时释放内存。
class MyClass 
{
public:static int staticData; // 声明静态数据成员int unstaticData = 10; //声明并初始化非静态成员
};int MyClass::staticData = 0; // 初始化静态数据成员int main() 
{MyClass obj1;MyClass obj2;obj1.staticData = 5;cout <<"非静态成员: " << obj1.unstaticData << endl; //输出非静态成员cout <<"静态成员: " << obj2.staticData << endl; // 输出静态成员: 5return 0;
}

在这里插入图片描述

  1. 静态成员函数:静态成员函数没有访问类的任何实例成员的权限,它们只能访问静态成员。静态成员函数可以通过类名或对象名来引用,非静态成员函数只能通过对象名引用。
class MyClass 
{
public:static void StaticFunction()//静态成员函数 {cout << "Static Function" << endl;}void UnstaticFunction()//非静态成员函数{cout << "UnStatic Function" << endl;}
};int main() {MyClass d1;MyClass::StaticFunction(); // 输出: Static Functiond1.UnstaticFunction();  //输出: UnStatic Functionreturn 0;
}

在这里插入图片描述
静态成员提供了一种在类的所有实例之间共享和访问数据的方式。在某些情况下,静态成员函数可以用作工具函数或全局函数的替代品。然而,静态成员应谨慎使用,因为它们破坏了封装性和面向对象设计的一些原则。


好啦,今天的内容就到这里啦,下期内容预告类和对象(五)友元、内部类、匿名对象等,下期就会对类和对象进行最后的收尾了,各位加油呐!


结语:今天的内容就到这里吧,谢谢各位的观看,如果有讲的不好的地方也请各位多多指出,作者每一条评论都会读的,谢谢各位。


🌏🗺️ 这里祝各位新年快乐 💞💞

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

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

相关文章

【Spring】定义过滤器Filter和拦截器Interceptor

# 定义过滤器 package com.holen.filter;import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import java.io.IOException;pub…

【Web】NSSCTF Round#18 Basic个人wp(部分)

目录 ①门酱想玩什么呢&#xff1f; ②Becomeroot ①门酱想玩什么呢&#xff1f; 先试一下随便给个链接 不能访问远程链接&#xff0c;结合评论区功能&#xff0c;不难联想到xss&#xff0c;只要给个评论区链接让门酱访问就可 我们研究下评论区 从评论区知道&#xff0c;要…

jmeter-问题三:如何在给接口命名,使得察看结果树更清晰

问题三&#xff1a;如何在给接口命名&#xff0c;使得察看结果树更清晰 jmeter中声明的变量在任意地方都可以引用&#xff0c;我们可以利用这一点来实现 解决方法&#xff1a; 场景&#xff1a;测试登录接口&#xff08;包含登录成功&#xff0c;密码错误&#xff0c;用户名…

Android---Jetpack Compose学习004

CompositionLocal 通常情况下&#xff0c;在 Compose 中&#xff0c;数据以参数形式向下流经整个界面树传递给每个可组合函数。但是&#xff0c;对于广泛使用的常用数据&#xff08;如颜色或类型样式&#xff09;&#xff0c;这可能会很麻烦。 为了支持无需将颜色作为显式参数…

- 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》

本文属于专栏《构建工业级QPS百万级服务》​​​​​ 1、前置知识 c的内存管理&#xff0c;主要说的是堆内存管理。现代计算机系统中&#xff0c;用户进程的堆内存&#xff0c;由内核映射。 堆内存的来源 主要是通过mmap()函数&#xff0c;在进程的虚拟地址空…

VueCLI核心知识综合案例TodoList

目录 1 拿到一个功能模块首先需要拆分组件&#xff1a; 2 使用组件实现静态页面的效果 3 分析数据保存在哪个组件 4 实现添加数据 5 实现复选框勾选 6 实现数据的删除 7 实现底部组件中数据的统计 8 实现勾选全部的小复选框来实现大复选框的勾选 9 实现勾选大复选框来…

OpenCV Mat 实例详解 二

构造函数 OpenCV Mat实例详解一中已介绍了部分OpenCV Mat构造函数&#xff0c;下面继续介绍剩余部分构造函数。 Mat (const std::vector< _Tp > &vec, bool copyDatafalse)&#xff1b; vec 包含数据的vec对象 copyData 是否拷贝数据&#xff0c;true— 拷贝数据&…

数据分析案例-基于亚马逊智能产品评论的探索性数据分析

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

亿级推送,得物是怎么架构的?

说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;很多小伙伴拿到一线互联网企业如阿里、网易、有赞、希音、百度、滴滴的面试资格。 最近&#xff0c;尼恩指导一个小伙伴简历&#xff0c;需要织入亮点项目、黄金项目。 前段时间&#xff0c;指导小伙写了一个《高…

AI在工业物联网(IIoT)中的安全管理与应用

在开放的工业互联网环境中&#xff0c;数百万个基于物联网的终端和中间设备&#xff0c;需要全天候地持续通信并保持在线状态。不过&#xff0c;这些设备往往由于最初设计上的限制&#xff0c;在机密性、完整性、可用性、扩展性、以及互操作性上&#xff0c;存在着各种安全漏洞…

Unity实现文字转语音并且与人物模型口型同步

文章目录 前言一、插件介绍二、导入RTVoice1.插件传送门2.组件配置 三、导入OVRLipSync1.插件传送门2.组件配置 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 今天我们用Unity实现文字转语音并且与人物模型口型同步&#xff0c;要实现这个功能&a…

Java安全 CC链6分析

CC链6分析 前言CC链分析核心transform链Lazymap类TiedMapEntry类HashMap方法 最终exp 前言 CC链6不受jdk版本与cs版本的影响&#xff0c;在Java安全中最为通用&#xff0c;并且非常简洁&#xff0c;非常有学习的必要&#xff0c;建议在学习CC链6之前先学习一下 URLDNS链 和 CC…

创建良好班风的重要性和意义

为什么有的班级总是充满活力&#xff0c;学生们团结友爱、学习热情高涨&#xff0c;而有的班级却显得沉闷&#xff0c;学生们缺乏动力&#xff0c;对学习毫无兴趣&#xff1f;其实&#xff0c;这背后的关键就在于班风的建设。 班风&#xff0c;简单说&#xff0c;就是一个班级…

IDEA在package下右键,没有new选项

正常情况下如下图&#xff0c;我们在文件夹上右键&#xff0c;是会出现New选项的。 但是今天我尝试将" add frameworks support"添加到右键时&#xff0c;竟然把New都删除了。如下图 搜遍全网&#xff0c;结果搜到的都是为什么在package或者文件夹上右键出现的Ne…

springboot185基于vue.js的客户关系管理系统(crm)的设计与实现

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

【Linux技术宝典】深入理解Linux基本指令:命令行新手指南

&#x1f4f7; 江池俊&#xff1a; 个人主页 &#x1f525;个人专栏&#xff1a; ✅数据结构冒险记 ✅Linux技术宝典 &#x1f305; 有航道的人&#xff0c;再渺小也不会迷途。 文章目录 一、Linux下基本指令1. ls 指令2. pwd指令3. clear指令4. cd指令什么是家目录&#xf…

基于AI Agent探讨:安全领域下的AI应用范式

先说观点&#xff1a;关于AI应用&#xff0c;通常都会聊准召。但在安全等模糊标准的场景下&#xff0c;事实上不存在准召的定义。因此&#xff0c;AI的目标应该是尽可能的“像人”。而想要评价有多“像人”&#xff0c;就先需要将人的工作数字化。而AI Agent是能够将数字化、自…

java基础实现的图书管理系统

文章目录 项目介绍项目功能代码讲解如何实现不同用户之间的操作权限不同 项目介绍 该项目是用的是javase的一些知识包括了类和对象封装&#xff0c;继承多态等面向对象的三大特性。主要是为了让我们能够更好的使用之前学到的知识。 接下来给大家讲解一下这个项目的一个特点。首…

31.File文件

File文件 1. 概述2. 构造方法2.1 方法2.2 代码示例 3. 成员方法3.1 判断、获取的方法3.1.1 方法3.1.2 代码示例 3.2 创建、删除的方法3.2.1 方法3.2.2 代码示例 3.3 获取、遍历的方法3.3.1 重点方法3.3.1.1 方法3.3.1.2 代码示例 3.3.2 所有方法3.3.2.1 方法3.3.2.2 代码示例 4…

OpenGL-ES 学习(4)---- OpenGL-ES 坐标体系

坐标体系 我们知道 OpenGL -ES 坐标系中每个顶点的 x&#xff0c;y&#xff0c;z 坐标都应该在 -1.0 到 1.0 之间&#xff0c;超出这个坐标范围的顶点都将不可见。 将一个物体&#xff08;图像&#xff09;渲染到屏幕上&#xff0c;通常经过将物体坐标转换为标准化设备坐标&am…