当前位置: 首页 > news >正文

c++初阶------类和对象(下)

作者前言

🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂
​🎂 作者介绍: 🎂🎂
🎂 🎉🎉🎉🎉🎉🎉🎉 🎂
🎂作者id:老秦包你会, 🎂
简单介绍:🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂
喜欢学习C语言、C++和python等编程语言,是一位爱分享的博主,有兴趣的小可爱可以来互讨 🎂🎂🎂🎂🎂🎂🎂🎂
🎂个人主页::小小页面🎂
🎂gitee页面:秦大大🎂
🎂🎂🎂🎂🎂🎂🎂🎂
🎂 一个爱分享的小博主 欢迎小可爱们前来借鉴🎂


类和对象

  • **作者前言**
  • 类的构造函数
    • 初始化列表
  • static成员
    • 静态成员
    • 静态成员函数
  • explicit关键字
    • 单参数的隐式类型转换
    • 多参数类型的隐式类型转换(c++11后支持)
  • 友元
    • 友元函数
    • 友元类
  • 内部类
  • 扩展
    • 拷贝小误区
    • 构造优化(编译器的优化)

类的构造函数

前面我们学习了类的构造函数的定义,如下:
在这里插入图片描述
这个就是我们之前写的构造函数的定义,叫做函数体内初始化,除了这样定义,还有另外一种定义叫初始化列表

初始化列表

使用这个主要是为了解决一些类型无法初始化

  1. 类中的引用无法初始化
    在这里插入图片描述
    可以看到使用函数体内初始化引用时是无法初始化引用变量的,因为在类中的成员是声明,在函数内才是定义(创建对象),const 也要在定义时初始化,为了解决引用和const在类的成员函数里面初始化不了,就有了初始化列表,
    初始化列表,初始化列表以冒号开头,后跟一系列以逗号分隔的初始化字段
		Date()//初始化列表:_a(d1._a),_b(30){//函数体内定义_year = d1._year;_month = (d1._month);_day = (d1._day);}

这里是一个类的默认构造函数,

  1. 假设初始化列表没有写内置类型的定义和函数体内定义也没有,内置类型就是随机值(编译器定义的)
  2. 如果类的成员有自定义类型,没有在初始化列表定义,自定义类型会自动调用它本身的默认构造函数。
    无参的构造函数全缺省的构造函数以及编译器自己生成的都称为默认构造函数
    (不用传参的构造函数)
namespace naco
{class D{public://默认构造D(int a = 20){_a = 20;}private:int _a;};class Date{public:Date(int year, int month, int day)//初始化列表:_a(year), _b(30),A(20)//不想调用自己默认值默认构造,就传值{//函数体内定义_year = year;_month = (month);_day = (day);}~Date(){cout << _year << "-" << _month << "-" << _day << endl;}private://声明int _year;int _month;int _day;int& _a;const int _b;D A;};
}

我们还可以在声明的时候定义,这样就可以哪怕初始化列表不写,也不会报错

class Date{public:Date(int year, int month, int day)//初始化列表:_a(year),A(20){//函数体内定义_year = year;_month = (month);_day = (day);}~Date(){cout << _year << "-" << _month << "-" << _day << endl;}private://声明int _year;int _month;int _day;int& _a;const int _b = 100;D A;//自定义类型};

所以可以总结一下:
初始化列表主要针对三类

  1. 引用
  2. const修饰的变量
  3. 没有默认构造函数的自定义类型成员,有默认构造的对象,哪怕没有定义也会调用自己的默认构造,或者是不使用默认值的自定义类型成员

建议:

  1. 构造函数由初始化列表和函数体构成,缺一不可,
  2. 每个成员只能再初始化列表出现一次,但是不会影响函数体内初始化,在函数体内还可以出现
  3. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关建议类中声明次序和初始化顺序一样
class A
{
public:A(int a):_a1(a),_a2(_a1){}void Print() {cout<<_a1<<" "<<_a2<<endl;}
private:int _a2;int _a1;
};
int main() {A aa(1);aa.Print();
}

在这里插入图片描述
结果是1和随机值,先初始化_a2,然后再初始化_a1
,

static成员

静态成员

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数静态成员变量一定要在类外进行初始化,
例子:
写出一个类,计算出一个程序中的类对象有多少个

class A
{
public:A(int a = 20){_a = a;++count;}A(const A& d1){_a = d1._a;++d1.count;}~A(){--count;}void Print(){cout << count << endl;}private://shngmstatic int count;//属于全部对象共同使用的.不会每个对象都有专属的count,而是全部对象公用这个countint _a;};
//静态成员定义
int A::count = 0;
int main()
{A a(10);A b(30);a.Print();return 0;
}

静态成员函数

  1. main函数之前就初始化了.而不是创建对象后才初始化,
  2. 只是放到类中,属于类的私有成员,
  3. 静态成员是全局的,所有对象共用,
  4. 静态成员只能在类外面定义,不属于类外访问,不能走构造函数的路
    静态成员访问形式:
A aa;
A::count;
aa.count;
//这两种都可以访问,

可能有些小可爱觉得不太方便,就会使用一下匿名对象,这个匿名对象和C语言的匿名结构体是不一样的,匿名对象的生命周期只是在一行中

class A
{
public:A(int a = 20){_a = a;++count;}A(const A& d1){_a = d1._a;++d1.count;}~A(){--count;}void Print(){cout << A::count << endl;}private://shngmstatic int count;int _a;};
//定义
int A::count = 0;
int main()
{A().Print();//A()是一个匿名对象,生命周期在这一行,出了这一行,这个匿名对象就会被析构return 0;
}

A()就是匿名对象,生命周期在定义的那一行中,

静态成员函数

特点:没有this指针
调用静态成员函数和调用静态成员的方法是一样的,

在这里插入图片描述
可以自定义类型::静态成员函数对象.静态成员函数调用

注意: 静态成员函数可以直接调用静态成员
作用

  1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
  2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
  3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问
  4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
  5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制
  6. 静态成员可以在类中直接使用,

explicit关键字

单参数的隐式类型转换

class A
{
public:A(int a = 20):_a(a){}A(const A& d1){_a = d1._a;}~A(){cout << _a << endl;}
private:int _a;
};
int main()
{A tes = 20;return 0;
}

上面代码涉及到了内置类型对象隐式转换成自定义类型对象
在这里插入图片描述
需要注意的是支持这个方式是要构造函数的参数只有一个int类型参数(this不包含在内),前面我们知道这个临时变量具有常性,需要用const修饰的变量来接收,
能隐式互相转的内置类型是整形(int)浮点数,这里两种对是类型相近的,表示数据的大小。

内置类型转自定义类型的话,前提是自定义类型的构造函数必须是单参数构造函数
还有就是全缺省构造函数。和只有一个参数没有默认值的半缺省构造函数,都可以隐式转化
简单的理解就是只能传一个参数的构造函数可以
在这里插入图片描述

多参数类型的隐式类型转换(c++11后支持)

上面是只能传一个参数的隐式转换,如果是多参数的话可以这样

class A
{
public:A(int a , int b = 20, int c=30):_a(a),_b(b),_c(c){}A(const A& d1){_a = d1._a;_b = d1._b;_c = d1._c;}~A(){cout << _a << endl;}
private:int _a;int _b;int _c;};
int main()
{A tes = {30, 20 ,10};const A& test = {60, 50, 10};//引用的是A(60,50,10)的临时变量return 0;
}

这里是要在c++11后才支持的,多参数的类型转换,一样的道理,

为了防止这些转换,cpp就有了一个explicit关键字

在这里插入图片描述
使用这个关键字来修饰构造函数就会防止有隐式转换了

友元

友元分为:友元函数和友元类

友元函数

友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。定义在外面就不要friend,

class A
{
public:A(int a , int b = 20, int c=30):_a(a),_b(b),_c(c){}A(const A& d1){_a = d1._a;_b = d1._b;_c = d1._c;}~A(){cout << _a << endl;}//友元函数(不是任何类的成员函数)friend std::ostream& operator<<(std::ostream& out, const A& d1);private:int _a;int _b;int _c;
};
std::ostream& operator<<(std::ostream& out, const A& d1)
{out << d1._a << d1._b << d1._c;//访问了类的私有成员,没有this指针return out;
}

特征

  1. ​友元函数可访问类的私有和保护成员,但不是类的成员函数

  2. 友元函数不能用const修饰

  3. 友元函数可以在类定义的任何地方声明,不受类访问限定符限制

  4. 一个函数可以是多个类的友元函数

  5. 友元函数的调用与普通函数的调用原理相同

友元类

class A
{public:friend class B;A(int a, int b = 20, int c = 30):_a(a), _b(b), _c(c){}A(const A& d1){_a = d1._a;_b = d1._b;_c = d1._c;}~A(){cout << _a << endl;}private:int _a;int _b;int _c;
};
class B
{
public:B(int a = 20, int b = 30, int c = 40, int Ba = 50, int Bb = 60, int Bc = 70):t(a,b,c),_Ba(Ba),_Bb(Bb),_Bc(Bc){}void Print(){cout << t._a << " " << t._b << " " << t._c << endl;//直接访问t的私有成员}~B(){cout << "B析构了" << endl;}private:int _Ba;int _Bb;int _Bc;A t;
};
int main()
{B te = 50;te.Print();return 0;
}

在这里插入图片描述
特征

  1. 友元关系是单向的,不具有交换性。(友元类可以访问普通类的私有成员或者成员函数,前提是普通类声明过这个友元类)
  2. 友元关系不能传递(C是B的友元类,B是A的友元类,但是C不是A的友元类)
  3. 友元关系不能继承

内部类

如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类
不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越
的访问权限。
注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访
问外部类中的所有成员。但是外部类不是内部类的友元。
如果内部类被public,可以在类外面进行定义,需要使用 外部类名:: 内部类,否则的话只能在外部类内定义使用,

class A
{
public:A(int a, int b, int c):bb(20){_a = a;_b = b;_c = c;}
private:class B{public:B(int b){_bb = b;}~B(){A aa(30,40,50);aa._a++;aa._b++;aa._c++;}private:int _bb;};private:int _a;int _b;int _c;B bb;//内部类
};
int main()
{A aa(1,1,1);//A::B bb(1);//内部类被oublic可以使用return 0;
}

特性:

  1. 内部类可以定义在外部类的public、protected、private都是可以的。
  2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。

扩展

拷贝小误区

class A
{
public:A(int a = 10){_a = a;}A(const A& d){_a = d._a;}
private:int _a;
};
int main()
{A a1;A a2 = a1;//拷贝A a3(20);a1 = a3;//赋值return 0;
}
  1. 一个存在的对象拷贝构造另一个要创建的对象,就是拷贝构造
  2. 两个存在的对象使用=就是赋值

构造优化(编译器的优化)

随着时代的变迁,编译器对于一些代码优化了很好,比如构造函数
同一个表达式中,连续的构造+构造/ 构造+拷贝构造/拷贝构造+拷贝构造合二为一

在这里插入图片描述
红框中的大概意思就是,用1构造一个临时对象,然后用这个临时对象拷贝构造a4,但是结果却是调用了构造函数,所以就会有一个结论:

构造 + 构造=>构造

拷贝构造+构造=>构造
在这里插入图片描述

拷贝构造 + 拷贝构造=>拷贝构造
在这里插入图片描述

不同的编译器优化成度不同,但是普遍有正常的优化,有一些编译器优化可能是多个表达式优化
比如VS2019:
在这里插入图片描述
Linux下的g++编译器
在这里插入图片描述
就可以看出差别,不同的编译器优化的程度会不同。

相关文章:

c++初阶------类和对象(下)

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…...

PMP考试:如何高效学习PMBOK?

PMBOK&#xff08;项目管理知识体系指南&#xff09;是PMP考试的核心教材&#xff0c;学习PMBOK对于备考PMP考试至关重要。那么我将分享一些高效学习PMBOK的方法和技巧&#xff0c;帮助同学们更好地掌握项目管理知识。 一、制定学习计划 在学习PMBOK之前&#xff0c;制定一个详…...

个人博客网站前端页面的实现

博客网站前端页面的实现 博客登录页 相关代码 login.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…...

Kotlin Retrofit 网络请求

一、添加依赖&#xff1a; //Retrofit 网络请求implementation("com.squareup.retrofit2:retrofit:2.3.0")implementation("com.squareup.retrofit2:converter-gson:2.3.0")//json转换 二、创建单例类&#xff1a; package com.example.buju.httpimport …...

pyside6 pytq PyDracula QVideoWidget视频只有声音没有画面

解决方案&#xff1a; 先不使用框架&#xff0c;纯pyside6代码&#xff0c;如果添加视频有画面有声音&#xff0c;那可以排除是硬件问题&#xff0c;如果没有画面只有声音&#xff0c;可能是视频解码器无法解码&#xff0c;换个格式的视频文件如果只有使用PyDracula 出问题&am…...

Python爬网页,不确定网页的编码,不需要用第三方库

Python爬网页&#xff0c;不确定网页的编码&#xff0c;不需要用第三方库&#xff0c;自己写个判断&#xff0c;乱拳打死老师傅 detect试了&#xff0c;不好用 apparent_encoding试了&#xff0c;不好用 encoding试了&#xff0c;不好用 headers里get试了&#xff0c;不好用…...

Web测试的基础流程(外加测试过程需要的注意5点)

前言 在Web工程过程中&#xff0c;基于Web系统的测试、确认和验收是一项重要而富有挑战性的工作。基于Web的系统测试与传统的软件测试不同&#xff0c;它不但需要检查和验证是否按照设计的要求运行&#xff0c;而且还要测试系统在不同用户的浏览器端的显示是否合适。 重要的是…...

项目解决方案:视频监控接入和录像系统设计方案(下)

目 录 1.概述 2. 建设目标及需求 2.1建设总目标 2.2 需求描述 ​2.3 需求分析 3.设计依据与设计原则 3.1设计依据 3.2 设计原则 4.建设方案设计 4.1系统方案设计 4.2组网说明 5.产品介绍 5.1视频监控综合资源管理平台介绍 5.2视频录像服务器和存储 5.2.…...

Python爬虫-使用Prefect框架实现一个可视化爬虫项目

前言 本文是该专栏的第19篇,后面会持续分享python爬虫干货知识,记得关注。 相信有的同学,在处理爬虫项目的时候,有时也会需要你将爬虫项目进行一个可视化展示,方便管理者能及时详细的了解当前爬虫任务的执行进度以及执行情况,甚至需要做一个爬虫监控预警的可视化任务。 …...

[hive面试真题]-基础理论篇

hive的工作流程 hive中分区表,分桶表 工作中hive分区表的应用示例 发现hive分区中的数据不对怎么处理 hive出现code 1 2 3 什么原因 ,怎么处理 工作中hive常见的文件格式 .压缩格式 工作时常用的hive函数 谈谈对窗口函数的理解 hive中如果出现数据倾斜 ,怎么发现 ,怎么…...

【其他】sd卡的照片在相机上能看到在电脑上却看不到

sd卡的照片在相机上能看到在电脑上却看不到 前情提要&#xff1a;太长不看版解决办法&#xff1a;思路&#xff1a;一、首先考虑恢复数据二、 解决文件后缀是exe的问题 前情提要&#xff1a; 在相机里可以看到照片和视频&#xff0c;但是SD卡通过读卡器插入电脑看不到&#x…...

Linux 之六:系统性能监控和挂载

系统性能 Linux系统中&#xff0c;有许多命令用于监测和分析性能指标。以下是一些常用的Linux性能分析命令&#xff1a; top&#xff1a;实时查看并监控CPU、内存以及各个进程的资源占用情况。htop&#xff08;需要安装&#xff09;&#xff1a;一个增强版的 top 命令&#x…...

【Web】浅聊Java反序列化之C3P0——JNDI注入利用

目录 简介 原理分析 EXP 前文&#xff1a;【Web】浅聊Java反序列化之C3P0——URLClassLoader利用 【Web】浅聊Java反序列化之C3P0——不出网Hex字节码加载利用 简介 出网的情况下&#xff0c;这个C3P0的Gadget可以和fastjson&#xff0c;Snake YAML , JYAML,Yamlbeans , …...

Java项目:基于Springboot+vue实现的付费自习室系统设计与实现(源码+数据库+毕业论文)附含微信小程序端代码

一、项目简介 本项目是一套基于Springbootvue实现的付费自习室系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、…...

C++写食堂菜品管理系统

说明:本博文来自CSDN-问答板块,题主提问。 需要:学校拟开发一套食堂菜品管理系统,以便对菜品和同学们的评价进行管理,其中包含如下信息: 商户:商户名称、柜面位置、电话…… 菜品:菜品编号、菜品名称、价格、所属商户…… 学生:注册账号、昵称、电话…… 食堂里的商户…...

vue 在线预览word

1 mammoth 先找的是mammoth这个插件yarn add mammoth,版本是1,7.0 参考网上的示例使用如下&#xff1a; import mammoth from "mammoth"; const vHtml ref("") const readExcelFromRemoteFile (url) >{var xhr new XMLHttpRequest();xhr.open("…...

七彩虹八渐变 外贸建站公司wordpress模板

进出口水果wordpress外贸模板 漂亮水果wordpress外贸模板&#xff0c;做水果进出品生意的外贸公司自建站官网模板。 https://www.jianzhanpress.com/?p3516 玩具wordpress外贸模板 简洁玩具wordpress外贸模板&#xff0c;适合做跨境电商外贸公司使用的wordpres外贸s网站主题…...

[C++] C++生成随机数

一、简介 在C语言中常使用srand()random()的方式生成随机数&#xff0c;该方式并不是一个很好的随据说生成方法&#xff0c;一方面是因为其生成的随机数质量较低&#xff0c;另一方面其随机数范围也有所限制。在C11中推荐使用随机数引擎的方式生成随机数。 如何高效得生成高质…...

web开发——前端html、css、JavaScript学习总结(持续更新中.......)

目录模版 1 html:结构标签/属性文本标记: mark文本设置:删除线del / 下划线ins/ 加粗b / 强调的文本em / 重要的文本 strong超链接: a联系信息: addressdiv 定义文档中的分区或节: div行元素:spanhtml结构: main / section / articlenav表格:table html中各种标签/属性的英文扩…...

LeetCode 2044.统计按位或能得到最大值的子集数目

给你一个整数数组 nums &#xff0c;请你找出 nums 子集 按位或 可能得到的 最大值 &#xff0c;并返回按位或能得到最大值的 不同非空子集的数目 。 如果数组 a 可以由数组 b 删除一些元素&#xff08;或不删除&#xff09;得到&#xff0c;则认为数组 a 是数组 b 的一个 子集…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

C# 表达式和运算符(求值顺序)

求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如&#xff0c;已知表达式3*52&#xff0c;依照子表达式的求值顺序&#xff0c;有两种可能的结果&#xff0c;如图9-3所示。 如果乘法先执行&#xff0c;结果是17。如果5…...

大数据驱动企业决策智能化的路径与实践

&#x1f4dd;个人主页&#x1f339;&#xff1a;慌ZHANG-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 一、引言&#xff1a;数据驱动的企业竞争力重构 在这个瞬息万变的商业时代&#xff0c;“快者胜”的竞争逻辑愈发明显。企业如何在复杂环…...