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

国外电商系统开发-运维系统文件上传-高级上传
如果您要上传文件到10台服务器中,有3台服务器的路径不是一样的,那么在这种情况下您就可以使用本功能,单独执行不一样的路径 点击【高级】上传...

【MongoDB】mongodb | 部署 | 常用命令
一、概述 基于mongodb的tcp连接无数据上报,服务器强踢监测。 物联网项目,tcp协议,基于4G卡,设备由于某些原因会断开重连,但是tcp没有断开,导致tcp持续累加,浪费资源。 建立机制: 当t…...

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

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

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

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

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

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 在大数据查询中的创新应用:优化数据获取效率
💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...

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

五、Python基础语法(程序的输入和输出)
一、输入 输入:输入就是获取键盘输入的数据,使用input()函数。代码会从上往下执行,当遇到input()函数,就会暂停执行,输入内容后,敲回车键,表示本次的输入结束。input函数得到的数据类型都是字符…...

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

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

代码随想录算法训练营第五六天| 99. 岛屿数量 100. 岛屿的最大面积
今日任务 99. 岛屿数量 深度搜搜 99. 岛屿数量 广度搜索 100. 岛屿的最大面积 99. 岛屿数量 题目链接: 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请求调试方法 总结
在我们使用微信开发者工具进行微信小程序开发的时候,在这个微信开发者工具的代码编辑框里面我们是无法像使用vscode, idea等IDE工具时那样直接对代码打断点进行调试, 原因是小程序实际上他就是一个web浏览器应用的包装, 在其内部使用的还是类似chrome的…...

注释,换行,控制台输入输出,命名空间,省略return语句
注释 1.单行注释 // 2.多行注释 /*注释内容*/ 解释代码的作用;注释多余内容;注释不会影响代码执行 换行 \nstd::endl 控制台输入输出 输出123456 可一次性输出多个 std::cout<<"123456"//示例获取控制台输入内容,存储在…...

宠物空气净化器该怎么选?希喂,小米、安德迈这三款好用吗?
不得不说,虽然现在购物网站的活动不少,可力度都好弱啊!我想买宠物空气净化器很久了,觉得有点贵,一直没舍得入手。价格一直没变化,平台小活动根本没什么优惠,只能寄希望于双十一了,准…...

【Mybatis篇】Mybatis的注解开发
🧸安清h:个人主页 🎥个人专栏:【计算机网络】,【Mybatis篇】 🚦作者简介:一个有趣爱睡觉的intp,期待和更多人分享自己所学知识的真诚大学生。 文章目录 🎯 Select注解 …...

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

Meta 发布 Quest 3S 头显及 AR 眼镜原型:开启未来交互新视界
简介 在科技的浪潮中,Meta 始终站在创新的前沿,不断为我们带来令人惊叹的虚拟现实和增强现实体验。2024 年 10 月 6 日,让我们一同聚焦 Meta 最新发布的 Quest 3S 头显及 AR 眼镜原型(Orion),探索这两款产品…...

【CSS】水平垂直居中
给父盒子设置属性 flex display: flex;写在父元素上这就是定义了一个伸缩容器justify-content:center 设置主轴对齐方式为居中,默认是横轴。子元素居中。align-items:center 设置纵轴对齐方式为居中,默认是纵轴。子元素居中。 给…...

欧盟零毁林法案 EUDR
EUDR法案,即欧盟零毁林法案(EU Deforestation Regulation),是欧盟为了减少全球森林砍伐和退化,应对气候变化和生物多样性丧失而制定的一项重要法规。以下是对该法案的详细解读: 一、法案背景与目的 EUDR法…...

26.删除有序数组中的重复项
题目::26. 删除有序数组中的重复项 - 力扣(LeetCode) 思路:只要不和前面的数一样就可以移动指针,进行赋值 代码: class Solution { public:int removeDuplicates(vector<int>& nums) {int slow 0 ;for(int fast 1; fast < …...

JAVA实现公众号扫码登录和关注功能实战
前言 使用第三方插件 <dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-mp</artifactId><version>4.6.0</version> </dependency>准备APPID和appSecet 登录微信公众号后台,复制ap…...

初识Mysql/备份,基础指令
1,MySQL登录指令: mysql -h 127.0.0.1 -P3306 -u -p 其中,-h指明登录部署了mysql服务的主机 -P指明要访问的端口号, -u指明登录用户 -p输入密码 2,数据库基础 mysql:表示的是客户端 mysqld&…...

没想到吧!线稿上色居然可以这么简单
前言 在创意无限的数字艺术世界里,艺术创作中的线稿上色,向来是件既费时又需技巧的活儿,寻找一款既能激发灵感又能简化繁琐流程的工具,是每位艺术家心中的向往。 今天,为大家推荐一款革命性的线稿上色AI工具——千鹿…...

修改Docker的默认存储路径
docker默认存储路径:/var/lib/docker/ 执行 docker info 查看,得到以下信息 Docker Root Dir: /var/lib/docker/Debug Mode: falseRegistry: https://index.docker.io/v1/Labels:Experimental: falseInsecure Registries: 1.修改docker配置 要修改默认…...

深入计算机语言之C++:C到C++的过度
🔑🔑博客主页:阿客不是客 🍓🍓系列专栏:从C语言到C语言的渐深学习 欢迎来到泊舟小课堂 😘博客制作不易欢迎各位👍点赞⭐收藏➕关注 一、什么是C C(c plus plusÿ…...

HR面试篇
一.面试中被问职业规划 HR感兴趣的不是你的职业规划,感兴趣的是你的职业规划和他们公司有没有关系。 或者说他们公司能不能去帮助你去实现你的职业规划。 切忌不要讲不合实际的,比如要在公司赚多少钱等等。 要根据公司的特点,找到切入点,只要讲得积极向上就可以。 二.…...