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

「C++」类和对象最终回

目录

前言

初始化列表:

使用及特点:

总结:

案例分析:

类型转换

单参数构造函数:

多参数构造函数:

static成员

友元

内部类

匿名对象

特点

使用方法:

匿名对象使用实例补充:

对象拷贝时的编译器优化

后记


前言

欢迎大家来到小鸥的博客,本篇将带你了解构造函数的初始化列表,构造函数传参时的类型转换,static成员,友元,内部类以及匿名对象等相关内容~


初始化列表:

在前面学习的构造函数实现中,初始化成员变量时使用的都是在函数体内进行赋值的方法,而构造函数还可以通过初始化列表来进行成员变量的初始化

使用及特点:

1. 初始化列表在函数参数列表后,以一个冒号开始,接着以逗号为分割,每个成员变量后面跟一括号来放初始值或者表达式:

	//Date(int year, int month, int day)Date(int year = 1, int month = 1, int day = 1):_year(year)//(year + 1),_month(month),_day(day){}

其中初始化列表的括号中可以是一个表达式;

2. 每个成员变量在初始化列表中只能出现一次,这是因为初始化列表的性质可以认为是成员变量定义初始化的地方,就和函数的声明和定义一样,定义有且只有一个

3. 引用成员变量,const成员变量,没有默认构造的类类型成员变量,都必须放在初始化列表中进行初始化,否则将会报错

原因:

  • 引用在定义时必须指定引用对象(类似指针必须指定指向的地址);
  • const修饰的变量必须在定义时赋值,后续也不能通过赋值来修改(const修饰具有常性);
  • 类类型的成员变量,定义时会调用默认构造函数,若只存在普通构造函数,又不给参数的话,其定义就会报错,但初始化列表中给它初始值之后,就相当于调用了该类的普通构造函数(传参)

例:

此处的i 和a 就是引用和const成员变量,由于初始化列表的性质类似与定义,所以可以在初始化列表中修改,而不能在函数体中进行修改。

4. C++11后支持在成员变量声明的位置给缺省值,这个缺省值就是为了在当一个成员变量没有显示在初始化列表中时使用。

此时_day成员没有在初始化列表中,也没有在函数体中进行赋值,所以d1对象定义完成后,得到的_day结果为2.

注意

  • 成员变量声明时的值是一个缺省值,而不是赋值,即只有既不在初始化列表中,也不在函数体中时,才会使用,和函数的缺省参数性质一样。
  • 成员变量声明处的缺省值,和构造函数参数中的缺省值要注意区分,前者是未显示在初始化列表中时使用,而后者是为了构造函数没有传参时使用的。

5. 初始化列表中是按照声明时的顺序进行初始化(因为开空间时的存放顺序就是按照声明的顺序存放的)的,和成员在初始化列表中的先后顺序无关,但建议保持一致。

总结:

(尽量不在函数体中赋值)

  • 每个构造函数都有初始化列表;
  • 每个成员变量都会进行初始化列表:

    1. 显示写在初始化列表中的成员,直接进行初始化;

    2. 不显示写在初始化列表中的成员:

      声明时有缺省值就用缺省值
      • 没有缺省值:

        内置类型成员变量:不确定,看编译器,大概率为随机值;自定义类型成员变量调用它的默认构造,没有则报错;
    3. 引用,const修饰,没有默认构造的类类型成员变量必须显示写在初始化列表中进行初始化

案例分析:

结果分析:

  1. 由声明顺序可知,_b先声明,所以先初始化,但由于此时_a还未进行初始化,所以_b初始化结果为零;
  2. _a初始化使用传值参数a的值进行初始化,所以结果为1;
  3. 综合可知:声明时成员变量的缺省值只有在对其自身初始化时起作用,_a在作为初始值为_b初始化时,还未进行初始化,所以_b结果为随机值,而不是_a的缺省值

类型转换

C++支持内置类型隐式转换为类类型对象,但要保证自定义类型兼容该内置类型,且类类型中存在兼容该内置类型的构造函数。

在构造函数前加上关键字explicit可以禁止该类型转换

单参数构造函数:

class A
{
public:void Print(){cout << _a << endl;}A(int i = 0):_a(i){}//拷贝构造函数A(const A& pa):_a(pa._a){}
private:int _a;
};class Stack
{
public:void Push(const A& a){//....}
private:A _arr[10];int top;
};int main()
{A aa1(1);//传参给构造函数进行正常构造aa1.Print();A aa3 = aa1;//调用拷贝构造// 隐式类型转换// 2先隐式转换为double,构造出一个A类型的临时对象,再将临时对象拷贝构造到aa2// 编译器中遇到构造+拷贝构造->优化为直接构造A aa2 = 2;aa2.Print();//A& raa2 = aa2;//引用//const A& raa3 = 2;//2类型转换产生临时变量具有常性,所以必须加上const才能引用Stack st;st.Push(aa1);st.Push(3);//int类型转换为A类型return 0;
}

上述代码中,构造函数加上explicit:

多参数构造函数:

class A
{
public:A(int a = 1, int b = 1):_a(a), _b(b){}private:int _a;int _b;
};
class Stack
{
public:void Push(const A& a){//....}
private:A _arr[10];int top;
};
int main()
{A aa1(2, 2);A aa2 = { 2,2 };Stack st1;st1.Push(aa1);st1.Push({ 2,2 });return 0;
}

参数为多个时,类型转换要用大括号括起来。

总结:C++支持隐式类型转换,是借助构造函数来进行的。

static成员

1. static修饰的成员变量,称为静态成员变量,静态成员变量必须在类外进行初始化

2. 静态成员变量是该类的所有对象共享的,不单独属于某个对象,也不存在对象中,而是存在静态区中,所有对象都可以调用

3. static修饰成员函数,叫做静态成员函数,静态成员函数不存在this指针

4. 静态成员函数只能访问其他静态成员函数,由于没有this指针,所以不能访问非静态成员变量

5. 非静态成员函数,可以随意访问静态成员变量和函数

6. 静态成员也受public,private,protected访问限定符的限制

7. 静态成员为public时,可通过 类名::静态成员 对象名::静态成员 两种方式来外部访问;

8. 静态成员声明时不能添加缺省值,因为静态成员要在类外部定义初始化,不属于某个对象,而声明时的缺省值是用于初始化列表进行初始化的,静态成员不走构造函数的初始化列表路线。

class A
{
public:static int _b;//开放静态成员,可外部访问static void func(){cout << _a << endl;cout << _b << endl;//cout << _c << endl;//3. 4. 静态成员函数没有this指针,无法调用非静态成员,报错}void Print(){cout << _a << endl;cout << _b << endl;cout << _c << endl;}void Set(int a){_a = a;}
private://1. 8. 声明时的缺省值用于初始化列表,而静态成员不在构造函数中定义,所以不能有缺省值//static int _i = 1;//错误static int _a;//私有静态成员int _c = 0;
};int A::_a = 1;
int A::_b = 1;int main()
{A aa1;      //_a _b _caa1.Print();// 1  1  0A aa2;//2. 对象aa2修改静态成员_a后,aa1打印出来_a也随之改变aa2.Set(2); //_a _b _caa1.Print();// 2  1  0A::func();// 2 1aa2.func();return 0;
}

友元

友元分为友元函数和友元类,其提供了一种突破类访问限定符封装的方式,将函数声明或者类声明的前面加上friend关键字,并且将其放到一个类里面,就构成了友元声明。

  1. 外部友元函数可以访问类的private和protected的成员,友元函数只是一个声明,而不会成为该类的成员函数
  2. 友元声明可以在类定义的任何地方声明,不受访问限定符的限制
  3. 一个函数可以是多个类的友元函数
  4. 友元类中的成员函数都可以是另一个类的友元函数,都可以访问另一个类中的private和protected成员;
  5. 友元类的关系是单向的,不具有交换性,若A类是B类的友元类,则B类可以访问A类的成员,但B类不是A类的友元类,就不能访问,除非也在B类中加上A类的友元声明;
  6. 友元关系不具有传递性,如果A类是B类的友元,B类是C类的友元,不代表A类就是C类的友元,而需要单独声明;
  7. 友元有时提供了一定的便利性,但友元会增加耦合度,破坏封装性,所以友元不宜多用。
class B;class A
{
public://PPrint是A类的友元函数,可以访问其方法和成员friend void PPrint(const A& aa, const B& bb);friend class B;A(char a = 'a', char b = 'a'):_a(a),_b(b){}void PrintA() const{cout << _a << endl;cout << _b << endl;}
private:char _a;char _b;
};
class B
{friend void PPrint(const A& aa, const B& bb);
public:B(char a = 'b', char b = 'b'):_a(a),_b(b){};void PrintB() const{cout << _a << endl;cout << _b << endl;}
private:char _a;char _b;
};
void PPrint(const A& aa, const B& bb)
{//友元可以访问private和protected成员cout << aa._a << endl;cout << bb._b << endl;
}
int main()
{A aa;B bb;PPrint(aa, bb);return 0;
}

内部类

如果一个类定义在另一个类的内部,则这个类成为该类的内部类。

  1. 内部类是一个独立的类,与定义在全局的类相比,只是受到了类域的限制和访问操作符的限制,所以一个类定义的对象中不会包含其内部类。
  2. 内部类默认是其外部类的友元类,反之不成立。
  3. 内部类也是一种封装,当A类和B类紧密关联,A类主要的作用就是为B类服务时,就可以设计为内部类,若放到private和protected中,那么A类就为B类的专属内部类,其它地方将无法使用。
class A
{
public://构造函数A(int a = 1):_a(a){cout << "A(int a = 1)" << endl;}//拷贝构造函数A(const A& aa){cout << "A(const A& aa)" << endl;_a = aa._a;}//析构函数~A(){cout << "~A()" << endl;_a = 0;}void PrintA(){cout << "void PrintA()" << endl;//B()._b;//不能直接调用B类的成员变量,需要友元声明B().PrintB(A());}
private:int _a = 1;//A类的私有内部类class B{public://friend class A;void PrintB(const A& aa){cout << "void PrintB(const A& aa)" << endl;//可以直接调用A类的成员变量,因为内部类默认为外部类的友元类cout << aa._a << endl;}private:int _b;};
};
int main()
{A a1(2);a1.PrintA();return 0;
}

 运行结果:

图示结果分析可知,对象a1先构造,然后调用PrintA函数,PrintA函数中创建了一个匿名对象来调用B类中的函数PrintB,所以打印出来的结果为1;

也说明B作为内部类可以直接调用A类的成员变量,是A的友元类,但反之A默认不是B的友元,需要单独声明。

匿名对象

特点

  • 用 类型(实参) 的方式定义出来的对象叫做匿名对象,而之前定义对象的方式 类型 对象名(实参) 定义出的对象叫有名对象
  • 匿名对象的生命周期只在其所在的一行,当需要定义一个对象临时使用时,就可以定义为匿名对象。

使用方法:

类名().成员函数();

#include <iostream>
using namespace std;class A
{
public:A(int a = 1):_a(a){cout << "A(int a = 1)" << endl;}A(const A& aa){cout << "A(const A& aa)" << endl;_a = aa._a;}~A(){cout << "~A()" << endl;_a = 0;}void Print(){cout << "void Print()" << endl;}
private:int _a = 1;
}int main()
{A().Print();//当前行结束后,匿名对象就会销毁return 0;
}

匿名对象使用实例补充:

万能头文件:<bits/stdc++> 会将常用的头文件一并包含。

  • 不建议日常使用,只在竞赛时节省时间时有用。

对象拷贝时的编译器优化

不影响正确性的前提下,对连续的构造和拷贝构造进行优化合并,从而减少拷贝消耗,提高代码速度

图中aa原本为隐式类型转换,先构造再拷贝构造,但编译器优化为直接构造,从而提升效率。

后记

感谢各位读者的阅读,欸,有不足的地方还是请大家继续指正哈~

本期专栏:C++_海盗猫鸥的博客-CSDN博客

个人主页:海盗猫鸥-CSDN博客

感谢各位的关注~

相关文章:

「C++」类和对象最终回

目录 前言 初始化列表&#xff1a; 使用及特点&#xff1a; 总结&#xff1a; 案例分析&#xff1a; 类型转换 单参数构造函数&#xff1a; 多参数构造函数&#xff1a; static成员 友元 内部类 匿名对象 特点 使用方法&#xff1a; 匿名对象使用实例补充&#…...

ELK:Elasticsearch、Logstash、Kibana Spring Cloud Sleuth和Spring Cloud Zipkin

〇、虚拟机中docker安装elasticsearch 、Kibana、Logstash elasticsearch导入中文分词器 Logstash修改es数据库ip及创建索引名配置 一、elasticsearch数据库的结构 和mysql作比较&#xff0c;mysql中的数据库的二维表相当于es数据库的index索引结构&#xff1b;mysql数据库的二…...

动态规划17:123. 买卖股票的最佳时机 III

动态规划解题步骤&#xff1a; 1.确定状态表示&#xff1a;dp[i]是什么 2.确定状态转移方程&#xff1a;dp[i]等于什么 3.初始化&#xff1a;确保状态转移方程不越界 4.确定填表顺序&#xff1a;根据状态转移方程即可确定填表顺序 5.确定返回值 题目链接&#xff1a;123.…...

华为OD机试真题---预定酒店

华为OD机试真题中的“预定酒店”题目是一道典型的算法题&#xff0c;主要考察的是如何在给定的酒店价格数组中找到最接近心理价位的k个酒店&#xff0c;并按价格从低到高输出。以下是对该题目的详细解析&#xff1a; 一、题目描述 放暑假了&#xff0c;小明决定到某旅游景点游…...

力扣242.有效的字母异位词

题目链接&#xff1a;242. 有效的字母异位词 - 力扣&#xff08;LeetCode&#xff09; 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的 字母异位词。 示例 1: 输入: s "anagram", t "nagaram"输出: true 示例 2: 输入: s &q…...

Android IP路由策略和防火墙

Android IP路由策略和防火墙 Platform: RK3368 OS: Android 6.0 Kernel: 3.10.0 文章目录 Android IP路由策略和防火墙ip route, ip rule, iptables简介ip routeip ruleiptables Android路由策略Android路由策略优先级命令查看当前路由策略 Android路由表命令查看路由表命令…...

MySQL insert ... select 语句锁表导致数据写不进去

问题现象 调用后台接口向表 t1 insert 写入数据时一直等待直到超时&#xff0c;猜测表 t1 被其它事务加锁了没有释放。 问题分析 在发生死锁时&#xff0c;通过执行下面命令查看事务和锁信息&#xff1a; select * from information_schema.INNODB_TRX 用来查看正在运行的事…...

Android摄像头Camera2和Camera1的一些总结

Android 系统对摄像头的同时使用有限制&#xff0c;不能同时使用摄像头进行预览或者录制音视频。 例如&#xff1a;界面上有两个SurfaceView, 这两个SurfaceView不能同时预览或者录制音视频&#xff0c;只能有一个正常工作&#xff08;一个SurfaceView预览前置摄像头&#xff…...

【Linux 从基础到进阶】Linux中的用户认证与授权

Linux中的用户认证与授权 1. 引言 在Linux系统中&#xff0c;**用户认证&#xff08;authentication&#xff09;和授权&#xff08;authorization&#xff09;**是两个核心的安全机制&#xff0c;用来控制系统资源的访问和管理用户操作权限。用户认证确保登录的用户是合法的…...

用户界面设计:视觉美学与交互逻辑的融合

1、什么是用户界面 用户界面&#xff08;UI&#xff09;是人与机器之间沟通的桥梁&#xff0c;同时也是用户体验&#xff08;UX&#xff09;的重要组成部分。用户界面设计包括两个核心要素&#xff1a;视觉设计&#xff08;即产品的外观和感觉&#xff09;和交互设计&#xff…...

ZK集群搭建:详细步骤与注意事项

在大数据和分布式系统日益重要的今天&#xff0c;ZooKeeper&#xff08;简称ZK&#xff09;作为一种分布式协调服务&#xff0c;扮演着举足轻重的角色。它主要用于管理大型分布式系统中的配置信息、命名、同步等。下面将详细介绍如何搭建一个ZooKeeper集群&#xff0c;帮助大家…...

如何将csdn文章导出为pdf

前言 在csdn上浏览文章的时候我发现有的文章支持pdf导出&#xff0c;但是有的文章不支持pdf导出&#xff0c;为了解决能将csdn上所有文章都能以pdf格式导出遂作此文。 正文 先上代码&#xff1a; (function(){use strict;var contentBox $("div.article_content")…...

【艾思科蓝】Imagen:重塑图像生成领域的革命性突破

【连续七届已快稳ei检索】第八届电子信息技术与计算机工程国际学术会议&#xff08;EITCE 2024&#xff09;_艾思科蓝_学术一站式服务平台 更多学术会议请看 学术会议-学术交流征稿-学术会议在线-艾思科蓝 目录 引言 一、Imagen模型的技术原理 1. 模型概述 2. 工作流程 …...

java类和对象(下): 封装 static成员 内部类

前言&#xff1a; 在前期的知识点中&#xff0c;我们学习了java中this函数的使用和相关的概念。这期我们将介绍封装的概念&#xff0c;以及常见内部类的使用&#xff0c;让我们开车吧&#xff01;&#xff01;&#xff01;&#xff01; 本期目录&#xff1a; 6. 封装 7. st…...

外包干了3周,技术退步太明显了。。。。。

先说一下自己的情况&#xff0c;大专生&#xff0c;21年通过校招进入武汉某软件公司&#xff0c;干了差不多3个星期的功能测试&#xff0c;那年国庆&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我才在一个外包企业干了3周的功…...

VIVO算法题——数位之积

记录算法究极无敌菜菜菜鸟的垃圾思维 题目&#xff1a; 现给定任意正整数 n&#xff0c;请寻找并输出最小的正整数 m&#xff08;m>9&#xff09;&#xff0c;使得 m 的各位&#xff08;个位、十位、百位 … …&#xff09;之乘积等于n&#xff0c;若不存在则输出 -1。 菜鸟…...

OPC Router快速打通设备层与influxDB数据通讯

随着时代演化&#xff0c;数据量呈几何倍数增加的情况下出现了时序数据库。时序数据库是基于时间进行存储的数据库&#xff0c;每一条数据中都有一个时间戳&#xff0c;这种数据库特别适合存储那些随着时间变化的数据&#xff0c;通过一些工具处理后&#xff0c;能够分析出数据…...

鸿蒙开发 四十四 ArkTs BuilderParam传递UI(二)

子组件多个BuilderParam&#xff0c;必须通过参数的方式传入&#xff0c;如果界面中有多个界面需要传递&#xff0c;可以定义多个尾随闭包&#xff0c;如图&#xff1a; 在自定义组件中调用&#xff1a; 在使用时候调用是作为参数传递给自定义的组件&#xff0c;参数是界面&…...

同期数分析-留存率

目录 同期数分析 加载数据 单月实现 统计每个月的订单量 求2月份的订单量和用户数量 求2月之前的历史订单量 筛选出2023年2月的新增的用户数 计算2023年2月在后面的留存情况 完整的2023年2月份同期群结果 遍历合并和分析 引入月份列表 遍历 调整成留存率的形式 回…...

Java前后端交互:构建现代Web应用

在现代Web应用开发中&#xff0c;前后端分离是一种常见的架构模式。后端通常负责数据处理和业务逻辑&#xff0c;而前端则负责用户界面和用户体验。Java作为后端开发的强大语言&#xff0c;提供了多种方式与前端进行交互。本文将探讨Java后端与前端交互的几种主要方式&#xff…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...