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

C++从入门到入土(五)——再谈构造函数

目录

前言

初始化列表

explicit关键字

static成员

友元

友元函数

友元类

内部类

总结


前言

前面我们通过介绍C++的六个默认成员函数,从而实现了日期类,但对于C++的类和对象而言,还有一些零碎的知识,比如:初始化列表,匿名对象,友元等问题,因此,本篇文章我将从以上几个方面再谈构造函数,由浅入深介绍上述知识点。

C++从入门到入土(四)--日期类的实现

C++从入门到入土(三)--6个默认成员函数

初始化列表

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

那么这个初始化列表与构造函数有什么关系呢?实际上,初始化列表是跟在构造函数后面的,以日期类为例:

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

如上所视,构造函数下面的就是初始化列表。

那么此时我们会有一个问题,为什么C++要引入初始化列表呢?初始化列表有什么用呢?我们以MyQueue为例,如果我们要使用Stack来实现MyQueue的功能,此时如果Stack没有默认构造,那么MyQueue也无法生成默认构造,因此为了解决这个问题,我们才引入了初始化列表,所以初始化列表的功能实际上是为了初始化成员变量而存在。

那么,初始化列表是如何完成初始化呢?我们在前面知道,C++11规定了成员变量在定义的时候可以给缺省值,那么这个语法是如何实现的呢?实际上这个缺省值是给初始化列表的,因此我们可以知道:初始化列表本质是成员定义的地方。

注意:

1.每个成员变量在初始化列表中只能出现一次,即:只能初始化一次

2.当类中包含const成员变量,引用成员变量,自定义类型成员变量(且没有默认构造函数)这三种只能在初始化列表位置初始化

3.尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定使用初始化列表初始化(初始化列表不管写不写,每个成员变量都会走一遍),实践中,先走初始化列表再走函数体

4.成员变量的声明次序就是在初始化列表中初始化顺序,原因在于:对象在内存中是按声明次序存放的

explicit关键字

在介绍explicit关键字之前,我们首先介绍一下隐式类型转换,当我们要将内置类型转换为自定义类型时会构造临时对象,这个临时对象再拷贝复制给自定义对象,当编译遇到连续的构造+拷贝构造则会直接优化为直接构造。那么explicit关键字与隐式类型转换有什么关系呢?实际上,explicit修饰构造函数能够禁止隐式类型转换。

static成员

概念:static修饰的类成员被称为类的静态成员;修饰成员变量称为静态成员变量;修饰成员函数被称为静态成员函数。其中对于静态成员变量需要在类外初始化。

特性:

1.static修饰的成员存在静态区,不存在对象中,在计算成员变量大小时不考虑

2.静态成员变量在定义的时候不能给缺省值,因为缺省值是给初始化列表,其初始化需要在类外初始化

3.静态成员函数不含隐藏的this指针,不能访问任何非静态成员

4.静态成员也是类的成员,受public,private,protected限制

class A
{
public:A(){++_a;}static int Fun(){//只能访问静态成员return _a;}
private://静态成员变量static int _a;
};
//静态成员变量在类外定义
int A::_a = 0;

友元

前面我们讨论过一个问题,当我们把函数重载为全局时无法访问私有,那么如何解决这个问题呢?我们可以提供这个成员的Get和Set,重载为成员函数,以及友元。

因此可以这么说,友元提供了一种突破封装的方式,其可以分为友元类和友元函数

友元函数

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

以前面我们写的重载流插入和流提取函数为例:

class Date
{friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);
public:Date(int year, int month, int day):_year(year), _month(day), _day(day){}
private:int _year = 1900;int _month = 1;int _day = 1;
};
ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "年" << d._month << "月" << d._day << endl;return out;
}
istream& operator>>(istream& in, Date& d)
{cout << "请依次输入年月日";in >> d._year >> d._month >> d._day;return in;
}

注意:

1.友元函数可以访问私有和保护成员,但不是类的成员函数

2.友元函数不能使用const修饰

3.友元函数可以在类的任何位置声明,不受类访问限定符限制

4.一个函数可以是多个类的友元函数

5.友元函数的调用与普通函数调用原理相同

友元类

注意

1.友元关系是单向的,不具有交换性和传递性

2.友元关系不能继承

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

class A
{friend class B;
public:A(int a=0,int b=0,int c=0):_a(a),_b(b),_c(c){}int Fun(){}
private:int _a;int _b;int _c;
};
class B
{
public:void SetofA(int a, int b, int c){_g._a = a;_g._b = b;_g._c = c;}
private:int _d;int _e;int _f;A _g;
};

如上述代码,我们创建了两个类A,B,在A中声明B是A的友元,那么在B中就可以访问A,通俗讲,B是A的朋友,那么B就可以去A的家里玩耍,但是A并没有把B当成朋友,所以A并不能去B的家里,也就是说,B可以访问A,但A并不能访问B

内部类

概念:如果一个类定义在另一个类的内部,这个类就叫内部类

注意:

1.内部类不属于外部,因此外部类不能访问内部类,但是内部类可以访问外部类,即:内部类天生就是外部类的友元

2.内部类可以定义在public,private,protected

3.内部类可以直接访问外部类的static成员

总结

本篇文章补充了C++中类和对象的方面的内容,分别介绍了初始化列表、隐式类型转换和explicit关键字、stctic成员、友元等相关知识,同时感谢您能在百忙之中抽空看完我的文章,受限于博主的知识水平,可能会有所纰漏,欢迎各位指正。如果本篇文章对您有所帮助的话,希望您能够点赞评论关注加转发,您的支持就是对我创作的最大鼓励。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • UDP_SOCKET编程实现
  • 2、electron vue3 怎么创建子窗口,并给子窗口路由传参
  • WEB攻防-JS项目Node.js框架安全识别审计验证绕过
  • 好用的工具网址
  • 【资料分析】刷题日记3
  • 代码随想录Day50|图论Part01,leetcode题目:98. 所有可达路径
  • 制作炫酷个人网页:用 HTML 和 CSS3 展现你的风格
  • JS基础之【对象详解 -- 对象的属性与方法、遍历对象与内置对象】
  • PCL 点云圆柱邻域搜索
  • 中国计算机学会(CCF)推荐中文科技期刊目录(2019年)
  • 【云原生监控】Prometheus之Alertmanager报警
  • SpringBoot 消息队列RabbitMQ 消息确认机制确保消息发送成功和失败 生产者确认
  • 什么是HTTP DDOS,如何防护
  • C++速通LeetCode中等第12题-矩阵置零(空间O(1)含注释)
  • xml中的转义字符
  • [译]CSS 居中(Center)方法大合集
  • 【Linux系统编程】快速查找errno错误码信息
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • CentOS从零开始部署Nodejs项目
  • Docker下部署自己的LNMP工作环境
  • JAVA之继承和多态
  • mysql中InnoDB引擎中页的概念
  • Node项目之评分系统(二)- 数据库设计
  • Python中eval与exec的使用及区别
  • Redux系列x:源码分析
  • scala基础语法(二)
  • VUE es6技巧写法(持续更新中~~~)
  • 创建一种深思熟虑的文化
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 工程优化暨babel升级小记
  • 聊聊flink的TableFactory
  • 码农张的Bug人生 - 初来乍到
  • 驱动程序原理
  • 吴恩达Deep Learning课程练习题参考答案——R语言版
  • 小程序01:wepy框架整合iview webapp UI
  • 写给高年级小学生看的《Bash 指南》
  • 《码出高效》学习笔记与书中错误记录
  • Semaphore
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • ​学习笔记——动态路由——IS-IS中间系统到中间系统(报文/TLV)​
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • # 透过事物看本质的能力怎么培养?
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • (C11) 泛型表达式
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第5节(封闭类和Final方法)
  • (附源码)ssm智慧社区管理系统 毕业设计 101635
  • (剑指Offer)面试题34:丑数
  • (接口封装)
  • (每日一问)操作系统:常见的 Linux 指令详解
  • (七)理解angular中的module和injector,即依赖注入
  • (贪心 + 双指针) LeetCode 455. 分发饼干
  • .bat批处理出现中文乱码的情况
  • .NET COER+CONSUL微服务项目在CENTOS环境下的部署实践
  • .net core 连接数据库,通过数据库生成Modell