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

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

🤑个人主页: 起名字真南
🤑个人专栏:【数据结构初阶】 【C语言】 【C++】

请添加图片描述

目录

  • 1 深入构造函数
  • 2 类型转换
  • 3 static成员
  • 4 友元函数
  • 5 内部类
  • 6 匿名对象

1 深入构造函数

  • 之前我们实现构造函数的时候,初始化成员变量都是在函数体内赋值,构造函数初始化还有另一个方式,就是初始化列表,初始化列表的使用方式是从一个冒号开始,成员变量之间用‘ ,’(逗号)分隔开,每个成员变量的后面都有一个括号里面存放着初始化的值或表达式。
  • 每个成员变量都只能在初始化列表中出现一次,可以理解为是每个成员变量进行定义初始化的地方。
  • 引用成员变量,const成员变量,没有默认构造的类类型成员变量,必须放在初始化列表的地方进行初始化,否则会编译报错
  • C++11支持在成员变量声明的地方给缺省值,这个缺省值目的是给没有显示在初始化列表初始化的变量使用的。
  • 使用初始化列表进行初始化,因为即便没有在初始化列表进行初始化编译器同样会经过初始化列表,如果在变量定义的时候给了缺省值那么就会用缺省值进行初始化,如果没有缺省值就会按照括号里的值或表达式进行初始化,对于没有在初始化列表显示的内置类型是否进行初始化却决于编译器,而对于自定义类型则会调用他的默认构造函数,如果没有默认构造就会造成编译报错。
  • 初始化列表的初始化顺序与该成员变量在初始化列表中的顺序无关,至于这个变量的声明顺序有关,先声明的先初始化。
    总结 :
    无论是否写初始化列表,每个构造函数都有初始化列表。
    无论是否在初始化列表显示初始化,每个成员变量都会走一遍初始化列表。

在这里插入图片描述

#include<iostream>
using namespace std;class Time
{
public:Time(int hour):_hour(hour){cout << "Time()" << endl;}
private:int _hour;
};
class Date
{
public:Date(int& x, int year = 1, int month = 1, int day = 1):_year(year), _month(month), _day(day), _t(12), _ret(x), _n(1){//只能在初始化列表初始化,不能再函数体内进行初始化//_ret = x;//_t = 12;//_n = 1;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;// 以下变量能且只能在初始化列表进行初始化Time _t;       //类类型成员变量   没有默认构造int& _ret;     //引用成员变量   const int _n;  //const类型成员变量
};
int main()
{int i = 0;Date d1(i);d1.Print();return 0;
}

运行结果如下:
在这里插入图片描述
虽然Time类型的成员变量都是内置类型成员变量,并且在初始化的时候可以不写默认构造但是由于在Time中已经写了一个构造函数所以不会生成默认构造,而在Date类中作为了自定义类类型的成员变量如果没有在初始化列表中初始化就会调用他的默认构造,因为它没有默认构造就会报错。
如果把初始化列表中的Time删除就会出现下面的错误:
在这里插入图片描述

class Time
{
public:Time(int hour):_hour(hour){cout << "Time()" << endl;}
private:int _hour;
};
class Date
{
public:Date():_month(1){cout << "Date()" << endl;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year = 1;int _month = 1;int _day;// 注意这里不是初始化而是给初始化列表提供了缺省值//如果初始化列表没有显示初始化,就是用这个缺省值初始化Time _t = 1;       int* _ret = (int*)malloc(sizeof(int) * 3);      const int _n = 1; 
};
int main()
{Date d1;d1.Print();return 0;
}

运行结果如下:
在这里插入图片描述

2 类型转换

  • C++支持内置类型隐式类型转换为类类型对象,需要有相关内置类型作为参数的构造函数
  • 构造函数前面加上explicit就不再支持隐式类型转换
  • 类类型对象之间也可以隐式类型转换,需要相对应的构造函数支持
#include<iostream>
using namespace std;class A
{
public://构造函数explicit就不再支持隐式类型转换// explicit A(int a1)A(int a1):_a1(a1){}A(int a1, int a2):_a1(a1),_a2(a2){}void print(){cout << _a1 << " " << _a2 << endl;}int get() const{return _a1 + _a2;}
private:int _a1 = 1;int _a2 = 2;
};
class B
{
public:B(const A& a):_b(a.get()){}
private:int _b = 0;
};
int main()
{A aa1 = 1;aa1.print();const A& aa2 = 1;//多参数传参用大括号A aa3 = { 3, 3 };aa3.print();cout << aa3.get() << endl;//A 类型 隐式转换为 B类型B b = aa3;const B& rb = aa3;return 0;
}

3 static成员

  • 用static修饰的成员变量叫做静态成员变量,必须要在类外进行初始化
  • 静态成员变量为所有类对象共享,不属于某个具体的对象,不存在对象中,存放在静态区中。
  • 用static修饰的成员函数称为静态成员函数,静态成员函数没有this指针。
  • 静态成员函数中可以访问其他的静态成员,但是不能访问非静态成员因为没有this指针。
  • 非静态成员函数可以访问任意的静态成员变量和静态成员函数
  • 突破类域就可以访问静态成员,可以通过类名::静态成员,对象.静态成员来访问静态成员变量和静态成员函数。
  • 静态成员也受public,private,protected等访问限定符限制。
  • 静态成员函数不能在声明的位置给缺省值进行初始化,因为缺省值是给构造函数初始化列表使用的,静态成员不属于某个对象,不走初始化列表。
#include<iostream>
using namespace std;class A
{
public:A(){++_scount;};A(const A& t){++_scount;}~A(){--_scount;}static int GetCount(){return _scount;}
private://类里面声明static int _scount;
};//类外面初始化
int A::_scount = 0;int main()
{cout << A::GetCount() << endl;A a1, a2;cout << A::GetCount() << endl;A a3(a1);cout << A::GetCount() << endl;cout << a3.GetCount() << endl;return 0;
}

运行结果:
在这里插入图片描述
第一次输出的结果是0,是因为我们在初始化的时候初始化的值为0,然后在每一次调用构造函数的时候就会加1,调用析构的时候减1,我们可以看到构造了a1,a2两个变量所以调用了两次++,然后在使用拷贝构造a3,调用构造函数在++所以这个时候的count是3,每次调用构造函数都会++,然后最后函数销毁时会自动调用析构函数,调用三次。

4 友元函数

  • 友元提供了一种突破类域访问限制的方法,友元分为:友元函数,友元类,在函数声明和类声明前面加上friend,并且把友元声明放到一个类里面。
  • 外部友元函数可以访问内部类的私有和保护变量,友元函数仅仅是一种声明并不是类的成员函数。
  • 友元函数可以在类定义的任何地方声明不受访问限定符的限制。
  • 一个函数可以是多个类的友元函数
  • 友元类的关系是单向的并不是双向的比如A是B的友元,但是B不是A的友元
  • 友元的关系不能传递,比如A是B的友元,B是C的友元,但A不是C的友元
  • 容易破坏封装不宜多用
#include<iostream>
using namespace std;class A; //前置声明为了调用函数的时候可以找到A类
class B
{friend void func(const A& aa, const B& bb);private:int _b1 = 1;int _b2 = 2;
};class A
{friend void func(const A& aa, const B& bb);private:int _a1 = 1;int _a2 = 2;
};void func(const A& aa, const B& bb)
{cout << aa._a1 << endl;cout << bb._b1 << endl;
}
int main()
{A a1, a2;B b1, b2;func(a1, b1);return 0;
}

在写上面的代码我们需要注意一个情况就是关于前置声明,因为编译器只会向上查找,在B类中的友元函数用到了A类所以我们需要在B类的前面提前声明A类告诉编译器A类存在。

class C
{friend class D;
private:int _c1 = 1;int _c2 = 2;
};class D
{
public:void func01(const C& cc){cout << cc._c1 << endl;cout << _d1 << endl;}void func02(const C& cc){cout << cc._c2 << endl;cout << _d2 << endl;}private:int _d1 = 3;int _d2 = 4;
};int main()
{C cc;D dd;dd.func01(cc);dd.func02(cc);return 0;
}

5 内部类

  • 如果一个类定义在一个类的内部,那么这个内部的类就叫做内部类,内部类是一个独立的类,跟定义在全局相比他只受外部类的类域和访问限定符限制,所以外部类定义的对象中不包含内部类。
  • 内部类默认是外部类的友元
  • 内部类本质上也是一种封装,如果A类和B类有紧密的联系,并且A类设计出来是专门为B类使用的那么就可以把B类设计为A类的内部类,B作为内部类可以访问A类的私有成员变量。
class AA
{
public:class BB{public:void func01(const AA& aa){cout << _k << endl;cout << aa._x << endl;}};
private:static int _k;int _x = 1;
};int AA:: _k = 2;int main()
{cout << sizeof(AA) << endl;AA aa;AA::BB bb;bb.func01(aa);return 0;
}

结果展示:
在这里插入图片描述
这里sizeof的大小是4的原因是_k是在静态区不算做A类里面

6 匿名对象

  • 用类型(实参)定义出来的对象叫做匿名对象,用类型 对象名 定义出来的对象叫做有名对象
  • 匿名对象的生命周期只在当前一行。
class AAA
{
public:AAA(int a = 0):_a(a){cout << "AAA(int a)" << endl;}~AAA(){cout << "~AAA()" << endl;}
private:int _a;
};
class Solution {
public:int Sum_Solution(int n) {//...return n;}
};
int main()
{//匿名对象的定义AAA();AAA(1);//有名对象AAA a2(2);Solution().Sum_Solution(10);return 0;
}

运行结果:
在这里插入图片描述
这里分别调用了三次构造三次析构证明对象确实存在生命周期只存在一行在下一个对象创建之后就已经销毁调用了析构

相关文章:

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

&#x1f911;个人主页: 起名字真南 &#x1f911;个人专栏:【数据结构初阶】 【C语言】 【C】 目录 1 深入构造函数2 类型转换3 static成员4 友元函数5 内部类6 匿名对象 1 深入构造函数 之前我们实现构造函数的时候&#xff0c;初始化成员变量都是在函数体内赋值&#xff0c…...

国外电商系统开发-运维系统文件上传-高级上传

如果您要上传文件到10台服务器中&#xff0c;有3台服务器的路径不是一样的&#xff0c;那么在这种情况下您就可以使用本功能&#xff0c;单独执行不一样的路径 点击【高级】上传...

【MongoDB】mongodb | 部署 | 常用命令

一、概述 基于mongodb的tcp连接无数据上报&#xff0c;服务器强踢监测。 物联网项目&#xff0c;tcp协议&#xff0c;基于4G卡&#xff0c;设备由于某些原因会断开重连&#xff0c;但是tcp没有断开&#xff0c;导致tcp持续累加&#xff0c;浪费资源。 建立机制&#xff1a; 当t…...

【Chrome浏览器插件--资源嗅探猫抓】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、资源嗅探插件---猫抓二、使用步骤总结 一、资源嗅探插件—猫抓 猫抓是一个浏览器插件&#xff0c;可以检测当前网页中的一些资源文件&#xff0c;可设置嗅探的…...

2.4Mybatis——缓存机制

2.4Mybatis——缓存机制 缓存配置一二级缓存一级缓存二级缓存 合集总览&#xff1a;Mybatis框架梳理 讲真&#xff0c;Mybatis缓存这块的记忆已经模糊了。刚好此时写测试用例出现一个BUG&#xff0c;就以这个问题作为切入点来梳理一下。 Testpublic void test(){Address ad…...

移动技术开发:文件的读取

1 实验名称 文件的读写 2 实验目的 掌握Android中读写文件的实现方法。 3 实验源代码 布局文件代码&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android&quo…...

Linux 中的 Makefile 伪目标详解

在 Linux 环境中&#xff0c;Makefile 是构建项目的重要工具&#xff0c;它通过定义规则&#xff0c;指导 make 工具如何编译和链接程序。通常我们会在 Makefile 中定义目标&#xff08;target&#xff09;&#xff0c;这些目标通常对应文件名。然而&#xff0c;有一种特殊类型…...

Java基础(中)

变量 成员变量与局部变量的区别 语法形式&#xff1a;从语法形式上看&#xff0c;成员变量是属于类的&#xff0c;而局部变量是在代码块或方法中定义的变量或是方法的参数&#xff1b;成员变量可以被 public,private,static 等修饰符所修饰&#xff0c;而局部变量不能被访问控…...

Leetcode热题100-200 岛屿数量

Leetcode热题100-200 岛屿数量 1. 题目描述2. 代码实现1. dfs算法2. bfs算法 1. 题目描述 200 岛屿数量 2. 代码实现 1. dfs算法 class Solution { public:int numIslands(vector<vector<char>>& grid) {int m grid.size(), n grid[0].size();int res 0…...

大数据新视界 --大数据大厂之 GraphQL 在大数据查询中的创新应用:优化数据获取效率

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...

swift使用代码结构解析

多模态模型的训练llamafactory也可以训练&#xff0c;但是总的来说&#xff0c;llamafactory对多模态模型的支持还是不太多&#xff0c;ms-swift支持的多模态模型更多&#xff0c;因此有时候去找框架是否够支持相应的模型时会有所困难&#xff0c;所以对这些框架的代码也要稍微…...

五、Python基础语法(程序的输入和输出)

一、输入 输入&#xff1a;输入就是获取键盘输入的数据&#xff0c;使用input()函数。代码会从上往下执行&#xff0c;当遇到input()函数&#xff0c;就会暂停执行&#xff0c;输入内容后&#xff0c;敲回车键&#xff0c;表示本次的输入结束。input函数得到的数据类型都是字符…...

【C语言】常见概念

文章目录 库函数关键字字符和ASCll编码字符串与\0转义字符语句和语句分类注释 库函数 为了不再重复实现常见的代码&#xff0c;让程序员提升开发效率&#xff0c;C语言标准规定了一组函数&#xff0c;这些函数再由不同的编译器厂商根据标准进行实现&#xff0c;提供给程序员使…...

Electron应用创建和打包

一、创建项目目录 创建NodeJs项目目录&#xff0c;项目有关的文件、依赖包都将在本目录创建和安装。 mkdir hello_electron & cd hello_electronCMD执行以上命令将在用户目录下创建hello_electron并进入该目录。当然也可以手动在任何地方创建目录&#xff0c;cmd中cd 路径…...

代码随想录算法训练营第五六天| 99. 岛屿数量 100. 岛屿的最大面积

今日任务 99. 岛屿数量 深度搜搜 99. 岛屿数量 广度搜索 100. 岛屿的最大面积 99. 岛屿数量 题目链接&#xff1a; 99. 岛屿数量 import java.util.Scanner;public class Main {public static int[][] dir {{0, 1},{1, 0},{-1, 0},{0, -1}};public static void dfs(boolean…...

图解 微信开发者工具 小程序源码 调试、断点标记方法 , 微信小程序调试器,真机调试断点调试方法,小程序网络API请求调试方法 总结

在我们使用微信开发者工具进行微信小程序开发的时候&#xff0c;在这个微信开发者工具的代码编辑框里面我们是无法像使用vscode, idea等IDE工具时那样直接对代码打断点进行调试&#xff0c; 原因是小程序实际上他就是一个web浏览器应用的包装, 在其内部使用的还是类似chrome的…...

注释,换行,控制台输入输出,命名空间,省略return语句

注释 1.单行注释 // 2.多行注释 /*注释内容*/ 解释代码的作用&#xff1b;注释多余内容&#xff1b;注释不会影响代码执行 换行 \nstd::endl 控制台输入输出 输出123456 可一次性输出多个 std::cout<<"123456"//示例获取控制台输入内容&#xff0c;存储在…...

宠物空气净化器该怎么选?希喂,小米、安德迈这三款好用吗?

不得不说&#xff0c;虽然现在购物网站的活动不少&#xff0c;可力度都好弱啊&#xff01;我想买宠物空气净化器很久了&#xff0c;觉得有点贵&#xff0c;一直没舍得入手。价格一直没变化&#xff0c;平台小活动根本没什么优惠&#xff0c;只能寄希望于双十一了&#xff0c;准…...

【Mybatis篇】Mybatis的注解开发

&#x1f9f8;安清h&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;【计算机网络】&#xff0c;【Mybatis篇】 &#x1f6a6;作者简介&#xff1a;一个有趣爱睡觉的intp&#xff0c;期待和更多人分享自己所学知识的真诚大学生。 文章目录 &#x1f3af; Select注解 …...

NEC协议

NEC协议是一种红外线通信协议&#xff0c;广泛应用于家电遥控器和其他红外线设备之间的通信。以下是对NEC协议的详细解释和介绍&#xff1a; 一、开发背景与应用 NEC协议由日本电子公司NEC&#xff08;日本电气公司&#xff09;开发&#xff0c;因其简单、易于实现和广泛兼容…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

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

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

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能&#xff1a;服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...