C++学习第四天(类与对象下)

1、构造函数的其他知识

构造函数体赋值

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

构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能称做初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值

初始化列表

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

class Date
{
public:Date(int year, int month, int day):_year(year),_month(month),_day(day){}
private:int _year;int _month;int _day;
};

【Attention】

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、尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表进行初始化

4、成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关,例如下面的例题:

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();return 0;
}

这个程序的结果是1 + 一个随机值 ,因为在类中先声明的是_a2 后声明的是_a1所以初始化列表中的初始化顺序也是按照这个顺序来的,先_a2 = _a1,此时_a1是一个随机值,所以_a2此时也得到的是一个随机值,然后_a1 = a,此时_a1的随机值被替换成了a的值,即是1

explicit关键字

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

class Date
{
public://1、单参构造函数,没有使用explicit修饰,具有类型转换的作用//explicit修饰构造函数,禁止类型转换---explicit去掉之后,代码可以通过编译explicit Date(int year):_year(year){}//2、虽然有多个参数,但是在创建对象时后用两个参数可以不传递,没有使用explicit修饰,其具有类型转换的作用//explicit修饰构造函数,禁止类型转换/*explicit Date(int year, int month = 1, int day = 1): _year(year), _month(month), _day(day){}*/Date& operator=(const Date& d){if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}
private:int _year;int _month;int _day;
};

将1给屏蔽掉,2放开时则编译失败,因为explicit修饰构造函数,禁止了单参构造函数类型转换的作用,总之,用explicit修饰构造函数,将会禁止构造函数的隐式转换

2、static成员

概念:

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

一个题目:实现一个类,计算程序中创建出多少个类对象

答:无非通过两种方式创建对象---构造函数和拷贝构造函数,所以我们只需要通过统计调用了多少次构造函数和拷贝构造函数即可,static在这里就可以体现出他的作用了

class A
{
public:A(){++count;}A(const A& t){++count;}//成员函数也可以是静态的,静态成员函数没有this指针static int GetACount(){return count;}
private://静态成员变量属于整个类,属于类的所有成员static int count;//声明
};
int A::count = 0;
int main()
{A a;A aa(a);cout << A::GetACount() << endl;return 0;
}

特性

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

【Attention】

1、静态成员函数不能调用非静态的成员函数,因为静态成员函数没有隐藏的this指针,不可以调用调用任何非静态成员

2、非静态成员函数可以调用静态的成员函数,因为非静态成员函数和静态的成员函数都是在类中定义的,所以在类中不受访问限定符的限制

3、友元

友元提供了一种突破封装的方式,有时候提供了便利,但是友元会增加耦合度,破坏了封装,所以要少用

友元函数 

情景:现在尝试去重载operator<<,但发现没有办法将operator<<重载成成员函数。因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置。this指针默认是第一个参数也就是左操作数了。但是实际使用中cout需要是第一个形参对象,才能正常使用。所以要将operator<<重载成全局函数。但是会导致没有办法访问成员,此时就需要友元来解决

class Date
{
public:Date(int year, int month, int day):_year(year), _month(month), _day(day){}// d1 << cout; -> d1.operator<<(&d1, cout); 不符合常规调用// 因为成员函数第一个参数一定是隐藏的this,所以d1必须放在<<的左侧ostream& operator<<(ostream& _cout){_cout << _year << "-" << _month << "-" << _day << endl;return _cout;}
private:int _year;int _month;int _day;
};

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

class Date
{friend ostream& operator<<(ostream& _cout, const Date& d);friend istream& operator>>(istream& _cin, 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& _cout, const Date& d)
{_cout << d._year << "-" << d._month << "-" << d._day;return _cout;
}istream& operator>>(istream& _cin, Date& d)
{_cin >> d._year;_cin >> d._month;_cin >> d._day;return _cin;
}int main()
{Date d;cin >> d;cout << d << endl;return 0;
}

【Attention】

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

友元类

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

  1. 友元关系是单向的,不具有交换性
    比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有成员变量则不行
  2. 友元关系不能传递
    如果C是B的友元,B是A的友元,则不能说明C是A的友元
  3. 友元关系不能继承
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(外部类)=  外部类,和内部类没有任何关系 
class A
{
private:static int k;int h;
public:class B{public:void foo(const A& a){cout << k << endl;cout << a.h << endl;}};
};int A::k = 1;
int main()
{A::B b;b.foo(A());return 0;
}

5、匿名对象

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

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

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

相关文章

Nginx+keepalived 高可用高性能

什么是高可用: 在使用 Nginx 做反向代理或者负载均衡的时候,都是以 Nginx 为入口,如果 Nginx 宕机了,那么所有的服务都无法正常提供,影响非常严重。所有我们需要保证 nginx 高可用,就是配置备份机,前一个挂了,还有后一个。 为了避免负载均衡服务器宕机造成严重影响,…

关于游戏报错提示x3daudio1_7.dll丢失怎么修复?多个实测有效方法分享

x3daudio1_7.dll 是一个与 Microsoft DirectX 相关的重要动态链接库&#xff08;DLL&#xff09;文件&#xff0c;它主要服务于Windows操作系统下的多媒体和游戏应用程序。 一、以下是关于 x3daudio1_7.dll 文件的详细介绍 名称与位置&#xff1a; 文件名&#xff1a;x3daud…

PHP堆栈+errLog定位

调用堆栈&#xff08;Call Stack&#xff09;是一个记录了程序在运行时所有活动子例程的栈结构。它以函数调用的方式描述了程序的执行流程和调用关系。 在PHP中&#xff0c;我们可以通过打印PHP调用堆栈来辅助调试和定位代码中的问题。本文将介绍如何在PHP中打印调用堆栈&…

探秘Python的Pipeline魔法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站AI学习网站。 目录 前言 什么是Pipeline&#xff1f; Pipeline的基本用法 Pipeline的高级用法 1. 动态调参 2. 并行处理 3. 多输出 …

Spring底层源码分析

spring依赖注入底层原理解析 spring之bean对象生命周期步骤详情 流程&#xff1a; UserService.class —>推断构造方法—>普通对象----依赖注入------>初始化&#xff08;afterPropertiesSet方法&#xff09;------>初始化后&#xff08;AOP&#xff09;------…

Zabbix“专家坐诊”第231期问答

问题一 Q&#xff1a;用docker-compose部署zabbix&#xff0c;部署完后如果要修改zabbix的配置应该要改docker-compose文件里的环境变量吧&#xff1f;改了环境变量之后只能重建容器才能生效吗&#xff1f;能不能在不影响已经配好的那些监控项的情况下让新的环境变量生效&#…

洛谷P1331海战

题目背景 在峰会期间&#xff0c;武装部队得处于高度戒备。警察将监视每一条大街&#xff0c;军队将保卫建筑物&#xff0c;领空将布满了 F-2003 飞机。 此外&#xff0c;巡洋船只和舰队将被派去保护海岸线。不幸的是&#xff0c;因为种种原因&#xff0c;国防海军部仅有很少…

win安装卸载python3.13

一、安装 访问python官网&#xff1a;https://www.python.org/ 点击“Downloads” 点击“Windows” 找到自己要下载的版本和位数&#xff0c;比如我这个是3.13版本、64位的安装包 下载好了之后&#xff0c;双击安装包 勾选“Add python.exe to PATH”&#xff1a;把python环…

[记录]-PyCharm中的Unresolved Reference疾病专治

转载https://blog.csdn.net/qq_36166962/article/details/115905359?ops_request_misc%257B%2522request%255Fid%2522%253A%2522170930227516800227476736%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id170930227516800227476736&biz_i…

作业1-224——P1331 海战

思路 深搜的方式&#xff0c;让它只遍历矩形块&#xff0c;然后在下面的遍历中判断是否出现矩形块交叉&#xff0c;但是很难实现&#xff0c;然后发现可以通过在遍历过程中判断是否合法。 参考代码 #include<iostream> #include<cstdio> using namespace std; …

SQLSERVER 2014 删除数据库定时备份任务提示失败DELETE 语句与 REFERENCE 约束“FK_subplan_job_id“冲突

SQLSERVER 2014 删除数据库定时备份任务提示失败DELETE 语句与 REFERENCE 约束“FK_subplan_job_id“冲突 &#xff0c;错误如图&#xff1a; 问题原因&#xff1a;不能直接删除作业 任务&#xff0c;需要先删除计划里面的日志、删除代理作业、删除子计划以后才能删除作业。 解…

蓝桥杯:真题讲解3(C++版)附带解析

报纸页数 来自&#xff1a;2016年七届省赛大学C组真题&#xff08;共8道题) 分析&#xff1a; --画出报纸长的样子&#xff0c;如果我们在上面多画一张报纸&#xff0c;那么就符合题意的5&#xff0c;6&#xff0c;11&#xff0c;12。 观察这张图&#xff1a;观察3&#xf…

VUE3子组件实例方法暴露(导出)方法

最近很多朋友私我请教子组件实例的获取方法 解答&#xff1a; vue2中可直接通过父组件内组件的ref读取子组件的实例&#xff0c;vue3有些许区别 vue3中需要在子组件中导出&#xff08;暴露&#xff09;相关实&#xff08;你需要再父组件中调用&#xff09;例方法&#xff1a;…

力扣:35. 搜索插入位置

力扣&#xff1a;35. 搜索插入位置 描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 示例 1: 输入: nums [1,…

Mybatis | Mybatis的核心配置

目录: Mybatis的核心配置 :一、MyBatis的 “核心对象”1.1 SqlSessionFactory1.2 SqlSession :SqlSession对象中的操作数据库的方法 :\<T> T selectOne ( String statement )\<T> T selectOne( String statement , Object parameter )\<E> List\<E> se…

SpringBoot基于注解实现全局日期格式化

首先根据项目要求提供自定义的日期序列化器和反序列化器&#xff0c;其中包括&#xff1a; DateJsonSerializerextendsJsonSerializer 表示将Date格式化为日期字符串。DateJsonDeserializerextendsJsonDeserializer 表示将日期字符串解析为Date日期。 使用注解 JsonComponent…

openGauss学习笔记-232 openGauss性能调优-系统调优-资源负载管理-资源管理准备-资源规划

文章目录 openGauss学习笔记-232 openGauss性能调优-系统调优-资源负载管理-资源管理准备-资源规划 openGauss学习笔记-232 openGauss性能调优-系统调优-资源负载管理-资源管理准备-资源规划 完成资源负载管理功能配置前&#xff0c;需要先根据业务模型完成租户资源的规划。业…

绍兴市新昌县人大一行莅临迪捷软件走访考察

2024年2月29日下午&#xff0c;绍兴市新昌县人大常委会副主任王敏慧一行莅临迪捷软件走访考察&#xff0c;绍兴市委科创委副主任、科创走廊建设领导小组副组长、市人大一级巡视员王继岗&#xff0c;绍兴市科技局副局长、科创走廊建设办公室常务副主任梁枫陪同。 王主任一行听取…

九州金榜|导致孩子厌学因素有哪些?家庭教育中要怎样解决?

现在如今孩子出现厌学的情况越来越严重&#xff0c;这也难坏了很多家长&#xff0c;众所周知&#xff0c;当下社会竞争越来越激烈&#xff0c;孩子的压力也越来越大&#xff0c;这也是导致孩子厌学的主要因素。其实家庭因素也是引起孩子厌学情绪产生的重要原因&#xff0c;在家…

数据结构——二叉树的基本概念及顺序存储(堆)

目录 一.前言 二.树概念及结构 2.1 树的概念 2.2 树的相关概念 2.3 树的表现 2.4 树在实际中的应用&#xff08;表示文件系统的目录树结构&#xff09; 三.二叉树的概念及结构 3.1 概念 3.2 特殊的二叉树 3.3 二叉树的性质 3.4 二叉树的存储结构 3.4.1 顺序存储 3…