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

【C++】:类和对象(3)

朋友们、伙计们,我们又见面了,本期来给大家解读一下有关Linux的基础知识点,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!

C 语 言 专 栏:C语言:从入门到精通

数据结构专栏:数据结构

个  人  主  页 :stackY、

C + + 专 栏   :C++

Linux 专 栏  :Linux

 

目录

引言:

1. 初始化列表

1.1 构造函数体赋值

1.2 初始化列表

1.3 explicit关键字

2. static成员 

2.1 概念

2.2 特性

3. 友元

3.1 友元函数

3.2 友元类

4. 内部类

5. 匿名对象

6. 拷贝对象时编译器做出的优化


引言:

本期我们继续承接上篇的类和对象(2)继续对类和对象进行收尾工作,在前面我们首先对类和对象做了基本介绍以及深入了解,然后自己实现了一个日期类,关于类和对象还有遗留的知识点,本期再来进行介绍。

1. 初始化列表

1.1 构造函数体赋值

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

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 初始化列表

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。

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){}
private:int _a;
};class B
{
public:B(int a, int ref):_aobj(a), _ref(ref), _n(10){}
private:A _aobj; // 没有默认构造函数int& _ref; // 引用const int _n; // const
};

3. 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。

class Time
{
public:Time(int hour = 0):_hour(hour){cout << "Time()" << endl;}
private:int _hour;
};class Date
{
public:Date(int day){}
private:int _day;Time _t;
};int main()
{Date d(1);return 0;
}

4. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。

class A
{
public:A(int a1, int a2, int a3)  //根据声明的次序来进行初始化:_a1(a1)  //2,_a2(a2)  //1,_a3(a3)  //3{}
private:int _a2;int _a1;int _a3;
};int main()
{A a(1, 2, 3);return 0;
}

总结:

不管写不写初始化列表,每一个成员都要走初始化列表,内置类型用随机值处理,自定义类型去调用去调用它的默认构造,,C++11支持在声明时给缺省值,这个值给初始化列表。

初始化列表使用场景:

1. 必须在定义时初始化的量

2. const修饰的常变量

3. 引用值

4. 自定义类型成员且无默认构造 

1.3 explicit关键字

构造函数不仅可以构造初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值的构造函数,还具有类型转换的作用。
 

class A
{
public:A(int i)//explicit A(int i)  //加上explicit可以阻止这种隐式类型的转化:_a(i){cout << "A(int i)" << endl;}A(const A& aa):_a(aa._a){cout << "A(const A& aa)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};int main()
{A a1(1);A a2 = 2; //从int转化为A是一种隐式类型转化// 用2调用A构造函数生成一个临时对象,再用这个对象去拷贝构造a2// 编译器会再优化,优化用2直接构造const A& ra = 2; //类型转化会产生临时变量,而临时变量具有常性,需要使用const修饰return 0;
}

用explicit修饰构造函数,将会禁止构造函数的隐式转换。 

2. static成员 

2.1 概念

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化

2.2 特性

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

//统计累计创建了多少个对象
class A
{
public:A() { ++_scount;++_scountCount;}A(const A & t) { ++_scount; ++_scountCount;}~A() { --_scount; }static int GetA_scount(){ return _scount; }static int GetA_scountCount(){return _scountCount;}
private://声明static int _scount;  //正在使用的对象static int _scountCount;  //累计创建的对象
};
//定义
int A::_scount = 0;
int A::_scountCount;A Func(A aa)
{return aa;
}int main()
{A a1, a2;   //创建两个对象Func(a2);   //拷贝构造时创建一个,返回值又创建一个cout << A::GetA_scount() << endl;cout << A::GetA_scountCount() << endl;return 0;
}

3. 友元

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用
友元分为:友元函数和友元类

3.1 友元函数

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

class Date
{//友元函数friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);public:Date(int year = 1900, int month = 1, int day = 1):_year(year),_month(month),_day(day){}
private:int _year;int _month;int _day;
};ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "/" << d._month << "/" << d._day << endl;return out;
}
istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;return in;
}
int main()
{Date d1;cin >> d1;cout << d1;return 0;
}

说明:

  • 友元函数可访问类的私有和保护成员,但不是类的成员函数
  • 友元函数不能用const修饰
  • 友元函数可以在类定义的任何地方声明,不受类访问限定符限制
  • 一个函数可以是多个类的友元函数
  • 友元函数的调用与普通函数的调用原理相同

3.2 友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。

  • 友元关系是单向的,不具有交换性。
  • 比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接
  • 访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。
  • 友元关系不能传递:如果C是B的友元, B是A的友元,则不能说明C时A的友元。
  • 友元关系不能继承(后续解析)
class Time
{friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成员变量
public:Time(int hour = 0, int minute = 0, int second = 0): _hour(hour), _minute(minute), _second(second){}
private:int _hour;int _minute;int _second;
};
class Date
{
public:Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}void SetTimeOfDate(int hour, int minute, int second){// 直接访问时间类私有的成员变量_t._hour = hour;_t._minute = minute;_t._second = second;}
private:int _year;int _month;int _day;Time _t;
};

4. 内部类

概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。


注意:内部类就是外部类的友元类,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。
特性:

  • 1. 内部类可以定义在外部类的public、protected、private都是可以的。
  • 2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
  • 3. sizeof(外部类)=外部类,和内部类没有任何关系。
    // 1、B类受A类域和访问限定符的限制,其实他们是两个独立的类
    // 2、内部类默认就是外部类的友元类
    class A
    {
    public:class B // B天生就是A的友元{public:void print(const A& a){cout << k << endl;   //可以直接访问A的静态成员变量cout << a.h << endl; //也可以访问A的成员变量}};
    private:static int k;int h;
    };
    int A::k = 1;int main()
    {A::B b;b.print(A());cout << sizeof(A) << endl;  //外部类的大小与内部类无关return 0;
    }

5. 匿名对象

匿名对象的特点就是不用取名字,生命周期只存在定义的这一行。

class A
{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};int main()
{A aa1;//A aa1();// 不能这么定义对象,因为编译器无法识别下面是一个函数声明,还是对象定义// 但是我们可以这么定义匿名对象,匿名对象的特点不用取名字,A();// 但是他的生命周期只有这一行,紧接着它的下一步就会自动调用析构函数A aa2(2);return 0;
}

应用场景: 当我们做C++的OJ题时会发现都是将其封装在一个Solution类中的,假设我们需要调用这个类中的某一个函数,是需要先创建一个Solution的对象,然后通过这个对象进行调用,这样的话有点麻烦,我们可以直接使用匿名对象来调用这个类中的成员函数。

class Solution {
public:int Sum_Solution(int n) {//...return n;}
};
int main()
{// 1.基本方法Solution sl;sl.Sum_Solution(10);// 2.匿名对象Solution().Sum_Solution(10);return 0;
}

6. 拷贝对象时编译器做出的优化

在传参和传返回值的过程中,一般编译器会做一些优化,减少对象的拷贝,这个在一些场景下还是非常有用的。
 

class A
{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}A(const A& aa):_a(aa._a){cout << "A(const A& aa)" << endl;}A& operator=(const A& aa){cout << "A& operator=(const A& aa)" << endl;if (this != &aa){_a = aa._a;}return *this;}~A(){cout << "~A()" << endl;}
private:int _a;
};
void f1(A aa)
{}
A f2()
{A aa;return aa;
}
int main()
{// 传值传参A aa1;f1(aa1);cout << endl;// 传值返回f2();cout << endl;// 隐式类型,连续构造+拷贝构造->优化为直接构造f1(1);// 一个表达式中,连续构造+拷贝构造->优化为一个构造f1(A(2));cout << endl;// 一个表达式中,连续拷贝构造+拷贝构造->优化一个拷贝构造A aa2 = f2();cout << endl;// 一个表达式中,连续拷贝构造+赋值重载->无法优化aa1 = f2();cout << endl;return 0;
}

朋友们、伙计们,美好的时光总是短暂的,我们本期的的分享就到此结束,欲知后事如何,请听下回分解~,最后看完别忘了留下你们弥足珍贵的三连喔,感谢大家的支持!

相关文章:

【C++】:类和对象(3)

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关Linux的基础知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通 数…...

windows创建服务:更新服务信息乱码问题(ChangeServiceConfig)

因为小项目需要创建windows服务&#xff0c;安装微软官方示例一切都挺顺利&#xff0c;代码运行后发现配置的信息在系统里显示乱码。打开注册表发现的确是乱码。这就排除软件读取得问题&#xff0c;而是调用ChangeServiceConfig系统函数写入时就发生了乱码。让我在网上查找了一…...

Spark 9:Spark 新特性

Spark 3.0 新特性 Adaptive Query Execution 自适应查询(SparkSQL) 由于缺乏或者不准确的数据统计信息(元数据)和对成本的错误估算(执行计划调度)导致生成的初始执行计划不理想&#xff0c;在Spark3.x版本提供Adaptive Query Execution自适应查询技术&#xff0c;通过在”运行…...

Angular+html+js前端加载生命周期

参考&#xff1a;document.readyState - Web API 接口参考 | MDN (mozilla.org) 第一步&#xff0c;JS生命周期第一步 文档加载中状态&#xff0c;document.readyState loading 第二步&#xff0c;JS生命周期第二步 可交互状态&#xff0c;document.readyState interacti…...

社区投稿| 以安全视角,深度剖析 Sui Staking 与 LSD

本篇技术研报由 MoveBit 研究团队的 Jason 撰写 #1 Sui Staking 介绍 1.1 Sui 网络概述 Sui 网络由一组独立的验证者运行&#xff0c;每个验证者在自己的机器或集群上运行独立的 Sui 软件实例。 Sui 采用委托权益证明&#xff08;DPoS&#xff09;来确定哪些验证者参与网络…...

AM@邻域@极限定义中的符号说明

文章目录 abstract邻域&#x1f47a;邻域中心和半径去心邻域 ϵ , δ \epsilon,\delta ϵ,δ的意义各种极限定义的共同点几何意义极限定义中的极限过程临界值 ϵ \epsilon ϵ的选取&#x1f47a; 概念辨析&#x1f47a;无限接近不同于越来越接近例例 越来越接近推不出无限接近 …...

论Oracle兼容性,我们需要做什么

作者介绍&#xff1a;王海峰&#xff0c;数据库系统架构师&#xff0c;YashanDB SQL开发负责人&#xff0c;10年以上数据库内核技术开发经验。 Oracle兼容性是目前国产数据库的关键任务之一&#xff0c;其直接影响到商业迁移的成本和竞争力。 我们经常发现&#xff0c;部分国产…...

你知道多号发圈的同时并延迟评论的方式吗?

你知道多号发圈的同时并延迟评论的方式吗&#xff1f; 其实很简单。 步骤1&#xff1a;编辑好朋友圈内容 步骤2&#xff1a;设置延迟评论 步骤3&#xff1a;选择多个号发圈 通过以上3个步骤&#xff0c;就可以实现多号发圈的同时并延迟评论。 在发布朋友圈前&#xff0c;只需要…...

【BugBounty】记一次XSS绕过

前言 最近一直在看国外的赏金平台&#xff0c;绕waf是真的难受, 记录一下绕过的场景。 初步测试 一开始尝试XSS&#xff0c;发现用户的输入在title中展示&#xff0c;那么一般来说就是看能否闭合&#xff0c;我们从下面图中可以看到&#xff0c;输入尖括号后被转成了实体。 …...

Linux文件目录结构详解:根目录和常见子目录介绍

文章目录 引言1. 什么是Linux文件目录结构2. Linux文件系统的重要性 根目录&#xff08;/&#xff09;2.1 根目录的作用和特点2.2 根目录下常见目录的介绍 /bin 目录3.1 /bin 目录的作用和内容3.2 常见的可执行命令示例 /etc 目录4.1 /etc 目录的作用和内容4.2 配置文件的存放位…...

知识付费小程序的推广与用户增长策略

在知识付费小程序开发完成后&#xff0c;推广和用户增长是关键的成功因素。本文将探讨一些推广策略和用户增长方法&#xff0c;并提供代码示例&#xff0c;帮助您在知识付费小程序中实施这些策略。 1. 社交媒体分享功能 在知识付费小程序中添加社交媒体分享功能&#xff0c;…...

微信小程序 获取当前屏幕的可见高宽度

很多时候我们做一下逻辑 需要用整个窗口的高度或宽度参与计算 而且很多时候我们js中拿到的单位都是px像素点 没办法和rpx同流合污 官方提供了wx.getSystemInfoSync() 可以获取到部分窗口信息 其中就包括了整个窗口的宽度和高度 wx.getSystemInfoSync().windowHeight 返回值为像…...

使用 Splashtop 驾驭未来媒体和娱乐

在当今时代&#xff0c;数字转型不再是可选项&#xff0c;而是必选项。如今&#xff0c;媒体与娱乐业处于关键时刻&#xff0c;正在错综复杂的创意、技术和远程协作迷宫之中摸索前进。过去几年发生的全球事件影响了我们的日常生活&#xff0c;不可逆转地改变了行业的运作方式&a…...

Tomcat项目启动报错

java.io.IOException: java.lang.ClassCastException: Cannot cast org.springframework.web.SpringServletContainerInitializer to javax.servlet.ServletContainerInitializer解决办法&#xff1a;可能Tomcat版本不对&#xff0c;使用7.0.90版本启动报错&#xff0c;使用8.0…...

offer

【录用通知书】 如何判断公司的好坏呢。 注意了&#xff0c;我们软件行业&#xff0c;技术管理类&#xff0c;技术类&#xff0c;产品类 好公司好企业基本都会给你说清楚&#xff0c;一项多少钱&#xff0c;加班多少钱&#xff0c;这样的 像这类公司的薪资结构复杂就要特别…...

漏洞复现--鸿运主动安全监控云平台任意文件下载

免责声明&#xff1a; **文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何…...

第二章 物理层 | 计算机网络(谢希仁 第八版)

文章目录 第二章 物理层2.1 物理层的基本概念2.2 数据通信的基础知识2.2.1 数据通信系统的模型2.2.2 有关信道的几个基本概念2.2.3 信道的极限容量 2.3 物理层下面的传输媒体2.3.1 导引型传输媒体2.3.2 非导引型传输媒体 2.4 信道复用技术2.4.1 频分复用、时分复用和统计时分复…...

路由高级特性

项目拓扑与项目需求 项目需求 某企业网络使用ospf和isis作为IGP协议实现内部网络的互联互通&#xff0c;区域规划和IP规划如图所示&#xff0c;现在要求实现如下需求&#xff1a; LSW1和AR1使用vlan10互联&#xff0c;与AR2使用vlan20互联&#xff0c;LSW1与LSW2、3、4之间使…...

【MySQL】数据库排查慢查询、死锁进程排查、预防以及解决方法

MySQL数据库排查慢查询、死锁进程及解决方法 一、排查慢查询 1.1检查慢查询日志是否开启 1.1.1使用命令检查是否开启慢查询日志: SHOW VARIABLES LIKE slow_query_log;如果是 Value 为 off 则并未开启 1.1.2开启并且查看慢查询日志: MySQL提供了慢查询日志功能,可以记录所…...

WSL2下的Docker配置和使用

在Windows的Linux子系统&#xff08;Windows Subsystem for Linux&#xff09;WSL2中安装、配置和使用 Docker&#xff0c;可以参考官方教程&#xff1a;WSL上的Docker远程容器入门. 重要步骤总结如下&#xff1a; 先决条件 确保你的计算机运行的是 Windows 10&#xff08;更…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

push [特殊字符] present

push &#x1f19a; present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中&#xff0c;push 和 present 是两种不同的视图控制器切换方式&#xff0c;它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...