C++ -4- 类和对象(下)

news/2024/3/29 22:52:59/文章来源:https://blog.csdn.net/fantastic_13_7/article/details/130337993

文章目录

  • 1.初始化列表
    • 什么是初始化列表?
    • 初始化列表的 意义及使用
  • 2.explicit关键字
    • 单参数构造函数(C++98)
    • 多参数的构造函数(C++11)(了解)
  • 3.static静态成员
    • 静态成员变量与静态成员函数
      • 静态成员变量
      • 静态成员函数
  • 4.匿名对象
  • 5.友元
    • 友元函数
    • 友元类
  • 6.内部类(C++很少用)
  • 7.拷贝对象时的一些编译器优化

1.初始化列表

什么是初始化列表?

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

例如:

class Date
{
public:Date(int year, int month, int day): _year(year)//以冒号开始, _month(month)//逗号分隔, _day(day)//括号中为初始值{}
private:int _year;int _month;int _day;
};

初始化列表的 意义及使用

在这里插入图片描述
在这里插入图片描述
(之所以没有默认生成构造函数是因为——默认生成的构造函数对内置类型不处理,但const 变量只有一次被定义的机会,必须要初始化)

  1. 不管哪个对象调用构造函数,初始化列表是它所有成员变量定义的地方
  2. 不管是否在初始化列表里有写,编译器每个变量都会在初始化列表被初始化
  3. 如果 const 变量有缺省值,只有当其他任何地方都没有给初始化值的时候才会用这个缺省值,即没给值才用缺省值
  • 注意:
  1. 每个成员只能初始化 一次
  2. 三类 必须初始化 的类型:
    • const
    • &引用
    • 没有默认构造函数的自定义类型
class Round
{
public:Round(int a)//这个不是默认构造函数,默认构造函数时不传参的!!:_a(a){}private:int _a;
};class Bottle
{
public:Bottle(int a, int ref):_rd(a), _b(ref), _n(13){}private:Round _rd;  // 没有默认构造函数int& _b;  // 引用const int _n; // const 
};
  1. 初始化的顺序是类中成员变量定义的顺序
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();
}output:-1  随机值
  1. 建议尽量使用初始化列表

2.explicit关键字

单参数构造函数(C++98)

分析一段代码:

class A
{
public:A(int a)//单参数构造函数:_a1(a){cout << "A(int a)" << endl;}A(const A& aa)//拷贝构造函数:_a1(aa._a1){cout << "A(const A& aa)" << endl;}private:int _a1;int _a2;
};void Testexplicit()
{A aa1(1);A aa2 = 1;A& variable = 13;const A& variable = 13;
}int main()
{Testexplicit();return 0;
}

在这里插入图片描述

🔊 explicit 不允许隐式类型转换:
在这里插入图片描述

多参数的构造函数(C++11)(了解)

class A
{
public:A(int a1, int a2)//多参数构造函数:_a1(a1), _a2(a2){}private:int _a1;int _a2;
};void Testexplicit()
{A aa3(1, 2);A aa4 = { 1,2 };
}

3.static静态成员

  • 如何统计 类的对象的个数

基本思路:创建 类的对象一定回去调用 构造函数 或者 拷贝构造函数

  1. 定义全局变量统计个数?
  • 代码:
int count = 0;
class A
{
public:A()//构造函数{++count;}A(const A& aa)//拷贝构造函数{++count;}private:int _a1;int _a2;
};void TestStatic()
{A a1, a2, a3, a4;cout << count << endl;
}
  • 问题:
  • 变量名冲突

报错:变量名 count 与 std 库发生冲突

error C2872: “count”: 不明确的符号
message : 可能是“int count”或 “iterator_traits<_Iter>::difference_type std::count(const _InIt,const _InIt,const _Ty &)”

所以,最好不要全局展开std

  • 容易出纰漏
    在这里插入图片描述

静态成员变量与静态成员函数

静态成员变量

  1. ✅静态成员变量:属于所有对象
  • 静态成员变量的声明和初始化:
class A
{static int count;//声明
};
int A::count = 0;//定义初始化

注意:静态成员变量声明处不能给缺省值,缺省值时给构造函数初始化用的,作用于非静态成员变量

  • 静态成员变量的访问:(以上述代码为例)

①当 静态成员变量 是 public

void TestStatic()
{A a1;a1.count;A::count;A* ptr = nullptr;  ptr->count;
}
  • 对象.count:A a1;a1.count;——创建对象,通过对象访问成员变量
  • A::count;
  • A* ptr = nullptr; ptr->count;

② 通过写函数访问

class A
{
public:A()//构造函数{++count;}A(const A& aa)//拷贝构造函数{++count;}int Getcount(){return count;}private:int _a1;int _a2;static int count;//声明
};int A::count = 0;//定义初始化void TestStatic()
{A a1;cout << a1.Getcount() << endl;
}

静态成员函数

void TestStatic()
{A a1;cout << a1.Getcount() << endl;
}

👆为了调用这个函数专门要创建一个对象?→如何改进?→『 静态成员函数

  • 什么是 静态成员函数:(示例)
static int Getcount()
{return count;
}
  • 如何调用静态成员函数:
    A::Getcount();

(完整示例:↓)

class A
{
public:A()//构造函数{++count;}A(const A& aa)//拷贝构造函数{++count;}static int Getcount(){return count;}private:int _a1;int _a2;static int count;//声明
};int A::count = 0;//定义初始化void TestStatic()
{A array[13];cout << A::Getcount() << endl;
}

ps.A array[13]; 自定义类型的数组,会自动调用13次构造函数。

  • 静态函数变量的特点:
    静态成员函数没有 this 指针,因此 不能访问非静态成员

4.匿名对象

  • 什么是匿名对象:
class A{};
A();//匿名对象
  • 匿名对象的特点:生命周期只在这一行

ps.临时变量和匿名对象都具有 常性


5.友元

友元分为 友元函数友元类,由于友元 破坏了封装 ,建议能不用就不用。

友元函数

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

示例:

class Date
{
public://流插入//函数声明friend void operator<<(ostream& out, const Date& d);private:int _year;int _month;int _day;
};//函数定义
void operator<<(ostream& out, const Date& d)
{out << d._year << "/" << d._month << "/" << d._day << endl;//友元函数可以直接访问类的私有成员
}//函数调用:
cout << d1; 👉 operator<<(cout,d1);

注意:

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

友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。 友元关系是单向的,不具有交换性。

在这里插入图片描述


6.内部类(C++很少用)

  • 概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个 独立(空间独立)的类,它不属于外部类!
  • 注意:内部类就是外部类的友元类,但是外部类不是内部类的友元。
  • 特性:
    1. 内部类可以定义在外部类的public、protected、private都是可以的。
    2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
    3. sizeof(外部类)=外部类,和内部类没有任何关系。内部类是独立的!

内部类可以看作是外部类的友元类,只是受外部类的类域限制。

class A
{
public:class B //内部类{public:void foo(const A& a){cout << k << endl;cout << a.h << endl;}};private:static int k;int h;
};int A::k = 1;
int main()
{A::B b;//类B受外部类A的类域限制b.foo(A());return 0;
}

7.拷贝对象时的一些编译器优化

1. 构造+拷贝 → 优化为直接构造
当构造和拷贝都在一个表达式里时才能优化:

  • 不在一个表达式:
    在这里插入图片描述

  • 在一个表达式:
    在这里插入图片描述

2. 传引用传参 → 不优化,没有拷贝

3. 传值返回 → 不优化(如下代码,构造和拷贝不能结合起来)

A func()
{A aa;//构造   “构造”return aa;//返回一份临时拷贝 “拷贝”
}

4.返回值接收:拷贝+拷贝 → 优化成一个拷贝

class A{};A func()
{A aa;//构造   “构造”return aa;//返回一份临时拷贝 “拷贝”
}int main()
{/*func(A());*/A aa1 = func();//拷贝接收//func()“拷贝”+aa1"拷贝构造" → “拷贝”+“拷贝”//如果写成:A aa2;aa2 = func();//这样写不优化return 0;
}

5. 返回匿名对象

class A{};A func()
{return A();
}

构造匿名对象 A() → “构造”
返回一个自定义对象,生成一份临时拷贝 → “拷贝”
构造+拷贝 → 优化为直接构造

sum.提高效率:
1.接收返回值对象,尽量用拷贝接收(4.)
2.返回值尽量用匿名对象(5.)
3.传参尽量用引用(2.)


END

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

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

相关文章

前端02:CSS选择器等基础知识

CSS基础选择器、设置字体样式、文本样式、CSS的三种引入方式、能使用Chrome调试工具调试样式 HTML专注做结构呈现&#xff0c;样式交给CSS&#xff0c;即结构&#xff08;HTML&#xff09;和样式CSS相分离 CSS主要由量分布构成&#xff0c;选择器以及一条或多条声明 选择器&…

18.Java泛型

目录 1. Java基本介绍 2. JDK下载安装及其环境配置 3. 一个简单的java程序 4. Eclipse基本使用、数据类型、运算符 5. 控制语句&#xff08;if、switch、for、while、foreach&#xff09; 6. Java数组 7. Java字符串对象(String|StringBuffer|StringBuilder|StringJoiner…

OFDM-LS信道估计 MMSE信道估计公式推导

假设ofdmN个子载波之间是完全正交的&#xff0c;即不考虑ICI影响&#xff0c;通过发送训练序列来实现信道估计。 其中&#xff0c;在推导6.8的时候&#xff0c;需要将6.6先拆解一下。 X − 1 Y X − 1 ( X H Z ) X − 1 X H X − 1 Z H X − 1 Z X^{-1}Y X^{-1}(XHZ)…

LeetCode213 打家劫舍 II 动态规划法

题目地址 https://leetcode.cn/problems/house-robber-ii/ 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋&#xff0c;每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 &#xff0c;这意味着第一个房屋和最后一个房屋是紧挨着的。同时&#xff0c;相邻的房屋装…

【Hive实战】探索Hive 2.X以及更早版本的MetaStore

探索Hive 2.X以及更早版本的MetaStore 文章目录 探索Hive 2.X以及更早版本的MetaStore概述配置元数据服务和元数据存储库基础配置参数其他配置参数默认配置配置元服务数据库使用内嵌模式的Derby库使用远程数据存储库 配置元数据服务本地/内嵌服务配置远程服务配置 元数据服务配…

【KingSCADA】什么是精灵图以及如何创建精灵图

大家好&#xff0c;我是雷工&#xff01; 本篇学习精灵图的制作&#xff0c;以下为学习内容及相关笔记。 一、什么是精灵图 精灵图是一种在外观上类似组合图&#xff0c;但内部嵌入了比较丰富的动画链接与逻辑控制&#xff0c;工程开发人员只要将其从精灵图库中调出来放置在开…

MySQL基础练习——创建数据库、数据表,并进行修改

目录 题目&#xff1a; 创建库和表&#xff1a; 创建库&#xff1a; 创建表&#xff1a; 将 c_contact 字段插入到 c_birth 字段后面&#xff1a; 将 c_name 字段数据类型改为VARCHAR(70)&#xff1a; 将 c_contact 字段改名为 c_phone&#xff1a; 将表名修改为 customer…

AD9208调试经验分享

背景概述 FMC137 是一款基于 VITA57.4 标准规范的 JESD204B 接口FMC 子 卡 模 块 &#xff0c; 该 模 块 可 以 实 现 4 路 14-bit 、 2GSPS/2.6GSPS/3GSPSADC 采集功能。该板卡 ADC 器件采用 ADI 公司的 AD9208 芯片&#xff0c;&#xff0c;与 ADI 公司的 AD9689 可以实现 …

量子力学 学习

对于同一个竖直向上量子比特&#xff0c;不对他进行任何的干扰&#xff0c;进行第一次水平测试实验会随机得到一个一或者负一&#xff0c;之后再进行多少次水平测试实验都与第一次的试验结果是相同的。 我们换用其他的竖直向上量子比特&#xff0c;或者对原来的量子比特进行干扰…

Matlab绘图中的一些技能

目录 1、matlab坐标轴设置多种字体(复合字体) 2、matlab图片中title生成的标题转移至图像下端 3、指定对应格式和期望dpi的图像进行保存、以及不留白保存 4、设置字体字号&#xff08;x、y轴&#xff0c;标题。全局字体等&#xff09; 5、设置刻度值信息&#xff0c;只有左…

引领文旅新体验!实时云渲染助力打造“永不落幕”的湾区文采会元宇宙

2022年11月25日至27日&#xff0c;2022年粤港澳大湾区公共文化和旅游产品&#xff08;东莞&#xff09;采购会&#xff08;简称“湾区文采会”&#xff09;在广东省东莞市文化馆举行。 文采会期间&#xff0c;文采会元宇宙线上虚拟展厅全新亮相&#xff0c;这艘承载着科技与文化…

5款十分小众的软件,知道的人不多但却很好用

今天推荐5款十分小众的软件&#xff0c;知道的人不多&#xff0c;但是每个都是非常非常好用的&#xff0c;有兴趣的小伙伴可以自行搜索下载。 1.视频直播录制——OBS Studio OBS Studio可以让你轻松地录制和直播你的屏幕、摄像头、游戏等内容。你可以使用OBS Studio来创建多种…

Mysql设置表只存储一段时间的数据

使用MySQL的事件调度器&#xff08;Event Scheduler&#xff09;来定期删除表中的数据。 假设你要删除的表是mytable&#xff0c;并且表中有一个名为created_at的日期时间类型的列&#xff0c;存储了每条记录的创建时间。你可以通过以下步骤设置表只存储30天的数据&#xff1a…

机器学习 协同过滤算法

协同过滤算法 协同过滤算法是根据已有的数据来推测出未知的数据&#xff0c;从海量的数据中找到相似度达到指定范围的数据&#xff0c;而这些数据成为你的邻居&#xff0c;系统将会为你推荐心仪的物品。 余弦相似法 通过计算两个向量的夹角余弦值来评估它们的相似度 修正余弦…

《站在巨人的肩膀上学习Java》

Java从诞生距今已经有28年了&#xff0c;在这段时间里&#xff0c;随着Java版本的不断迭代&#xff0c;Java新特性的不断出现&#xff0c;使得Java被使用的越来越广泛。在工程界Java语言一直是大家最喜欢的语言之一&#xff0c;Java一直排行在编程语言热门程度的前3名。 可想而…

从0搭建Vue3组件库(六):前端流程化控制工具gulp的使用

随着前端诸如webpack&#xff0c;rollup&#xff0c;vite的发展&#xff0c;gulp感觉似乎好像被取代了。其实并没有&#xff0c;只不过它从台前退居到了幕后。我们仍然可以在很多项目中看到它的身影&#xff0c;比如elementplus、vant等。现在gulp更多的是做流程化的控制。 比如…

delta.io 参数 spark.databricks.delta.replaceWhere.constraintCheck.enabled

总结 默认值true 你写入的df分区字段必须全部符合覆盖条件 .option("replaceWhere", "c2 == 2") false: df1 overwrite tb1: df1中每个分区的处理逻辑: - tb1中存在(且谓词中匹配)的分区,则覆盖 - tb1中存在(谓词中不匹配)的分区,则append - tb1中不存…

今天试了试chatgpt

今天试了试chatgpt&#xff0c;真是服了 arcade&#xff1f; Arcade是一个Python游戏开发库&#xff0c;它提供了一系列的工具和函数&#xff0c;可以帮助开发者快速地创建2D游戏。以下是Arcade的一些特点&#xff1a; 简单易用&#xff1a;Arcade提供了简单易用的API&#x…

Android分屏流程分析

本文基于Android 11。 SystemUI模块中的Divider管理着所有关于分屏的对象&#xff1a; DividerView&#xff08;分屏分割线&#xff0c;分屏显示界面&#xff09;SplitScreenTaskOrganizer&#xff08;分屏Task组织者&#xff0c;分屏逻辑&#xff09; 这里重点关注分屏逻辑…

Qt如何生成dump文件和pdb文件并进行调试定位

在main文件中增加下面代码用于可生成dump文件 #include "widget.h" #include <QApplication> #include <QDir> #include <QDateTime> #ifdef Q_OS_WIN#include <windows.h>#include <dbghelp.h> #endifstatic LONG WINAPI exceptionC…