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

类和对象终

一、初始化列表

再谈构造函数

  1. 我们之前实现构造函数的时候,初始化成员变量在函数体内赋值的,构造函数还有一种初始化方式,就是初始化列表
    我们先实现一个栈来举例:
// 实现一个栈
typedef int DataType;
class Stack {
public:// 默认构造Stack(size_t capacity = 4) {_arr = (DataType*)malloc(sizeof(DataType) * capacity);if (_arr == nullptr) {perror("_arr malloc err!");return;}_capacity = capacity;_top = 0;}void Push(DataType val) {_arr[_top++] = val;}// 其他方法实现~Stack() {if (_arr) {free(_arr);_arr = nullptr;_top = _capacity = 0;}}
private:DataType* _arr;int _top;size_t _capacity;
};
// 两个栈实现一个队列
class MyQueue {
private:Stack _pushst;Stack _popst;int _top;
};
int main() {MyQueue q;return 0;
}

我们不写MyQueue的构造函数,编译器会默认生成MyQueue的默认构造函数,对于自定义类型,会去调用它的默认构造函数,而对于内置类型,编译器处理or不处理是未知的,取决于编译器
在这里插入图片描述

但是如果Stack没有默认构造的话,MyQueue里的自定义类型去调用Stack中的默认构造就会失败
在这里插入图片描述

  1. 初始化列表的使用方式是以一个冒号开始,逗号分隔的数据或成员列表,每个成员变量后面跟一个括号,括号里面是初始化的值或者表达式
  2. 每个成员变量在初始化列表中只能出现一次,本质可以理解为每个对象中的成员定义的地方
  3. const成员变量、引用成员变量、没有默认构造的类类型变量(必须显式传参调用构造),必须放在初始化列表初始化,否则会报错
typedef int DataType;
class Stack {
public:// 默认构造Stack(size_t capacity = 4) {_arr = (DataType*)malloc(sizeof(DataType) * capacity);if (_arr == nullptr) {perror("_arr malloc err!");return;}_capacity = capacity;_top = 0;}void Push(DataType val) {_arr[_top++] = val;}// 其他方法实现~Stack() {if (_arr) {free(_arr);_arr = nullptr;_top = _capacity = 0;}}
private:DataType* _arr;int _top;size_t _capacity;
};
// 两个栈实现一个队列
class MyQueue {
public:// 若Stack不具备默认构造,那么MyQueue也无法生成默认构造// 1、引用 2、const 3、没有默认构造自定义类型成员(必须显示传参调构造)MyQueue(int n, int& rr):_pushst(n), _popst(n), _top(0),_val(1),_ref(rr){}
private:Stack _pushst;Stack _popst;int _top;// 必须在定义时初始化// C++11给缺省值const int _val = 0;int& _ref;
};
int main() {int aa = 0;MyQueue q1(10,aa);return 0;
}

const修饰的变量和引用变量,它只有一次初始化的机会,就是在定义的时候,所以我们说初始化列表本质就是每个对象中成员定义的地方
5. C++11对缺省值做了补充,给在private中声明的成员变量赋值本质是给缺省值
在这里插入图片描述

  1. 以后尽量使用初始化列表初始化,因为那些不在初始化列表初始化的成员也会先走一边初始化列表,如果这个成员在声明位置给了缺省值,初始化列表就会使用这个缺省值初始化。如果没有给缺省值,对于没有显式在初始化列表初始化的内置类型成员是否会初始化取决于编译器;而没有显式在初始化列表的自定义类型成员,会调用自己的默认构造函数,无默认构造函数,则会报错
  2. 成员变量在类中声明次序就是在初始化列表中初始化顺序
#include<iostream>
using namespace std;
class A
{
public:A(int a):_a1(a), _a2(_a1) {}void Print() {cout << _a1 << " " << _a2 << endl;}
private:int _a2 = 2;int _a1 = 2;
};
int main()
{A aa(1);aa.Print();
}

这段代码的输出结果是什么?打印1 随机值
分析:

  1. 声明顺序_a2 _a1
  2. 初始化顺序_a2 _a1
    所以,_a1赋值给_a2,_a2 是随机值,虽然给了缺省值,_a1的缺省值为2,但是这个缺省值只能在初始化_a1的时候使用,而_a2 并没有接收自己的缺省值,因为手动给了_a1,此时_a1是随机值,然后a赋值给_a1 _a1 = 1
    所以最后打印:1 随机值

总结

  • 无论是否显示写初始化列表,每个构造函数都有初始化列表;
  • 无论是否在初始化列表显示初始化成员变量,每个成员变量都要走初始化列表初始化

在这里插入图片描述

二、 类型转换

  1. CPP支持内置类型隐式转换为类类型对象,但需要相关内置类型为参数的构造函数
  2. 构造函数前⾯加explicit就不再⽀持隐式类型转换
  3. 类类型对象之间也可以隐式转换,但需要相关构造函数
// 类型转换
class classA {
public:// 单参数构造classA(int a):_aa(a){cout << "classA(int a)\n";}// 多参数构造classA(int a1, int a2):_a1(a1), _a2(a2){cout << "classA(int a1, int a2)\n";}
private:// 声明给缺省值int _aa = 0;int _a1 = 1;int _a2 = 3;
};int main() {classA a1(1);// 拷贝构造classA a2 = a1;// 隐式类型转换// 3构造了一个classA的临时对象,再用这个临时对象拷贝构造a3// 这里经历了构造、拷贝两个过程,编译器优化为一步,直接构造classA a3 = 3;// raa 引用的是类型转换中用3构造的临时对象 const classA& raa = 3;// 多参数传参用大括号classA aa1 = { 1 , 2 };const classA& raaa = { 1 , 3 };return 0;
}

在这里插入图片描述
在这里插入图片描述

三、static成员

  • 静态成员变量要在类外进行初始化
  • 静态成员变量被所有类对象共享,不属于某个对象,存放在静态区
  • 静态成员函数中可以访问其他的静态成员,但是不能访问⾮静态的,因为没有this指针
  • 非静态的成员函数,可以任意访问静态的成员变量和静态的成员函数
  • 可以通过::静态成员或者对象.静态成员来访问静态成员和静态成员函数
  • 静态成员也是类的成员,受publicprotectedprivate访问限定符限制
  • 静态成员变量不能在声明位置给缺省值初始化,因为缺省值是构造函数初始化列表的,静态成员变量不属于任何对象,不走初始化列表
// 实现一个类 计算创建出了多少类对象
// 有对象的创建就++ 有析构就-- ,用静态变量存储这个值,最后返回最终值
class classB {
public:classB() {++_SumCnt;}classB(const classB& t) {++_SumCnt;}~classB() {--_SumCnt;}static int GetBCount() {return _SumCnt;}// 类里面声明// 不能给缺省值,因为缺省值是给初始化列表// 在静态区而不在对象中,不走初始化列表static int _SumCnt;
private:int _b1;int _b2;
};
classB func() {classB bb4;return bb4;
}// 类外面初始化 即定义
int classB::_SumCnt = 0;int main() {classB bb1;cout << sizeof(bb1) << endl;classB bb2;classB bb3(bb2);func();// 直接访问cout << classB::GetBCount() << endl;}

注意看sizeof(bb1)的大小,private中有两个int类型成员变量,public中有一个int类型静态成员变量
到底是12还是8呢?答案是8,因为静态成员变量存在静态区,不属于任何一个对象
对于创建了几个对象的问题bb1 bb2 bb3 bb4在一个栈区的函数中创建,出函数作用域生命周期就结束了,所以总共有三个对象被创建

四、友元函数

  • 友元提供了一种突破类访问限定符封装的方式,分为友元类友元函数,在函数声明的前面加friend,并将友元的声明放到一个类的里面
  • 外部友元函数可以访问私有保护成员,友元函数仅仅是一种声明,声明我是这个类的朋友,我有权限访问这个类的数据,但是它不是类的成员
  • 一个函数可以是多个类的友元函数
  • 友元类的成员函数可以是另一个类的友元函数,都能访问另一个类中的私有和保护成员
  • 友元类的关系是单向的,不能传递的,A是B的友元,但B不是A的友元,A是B的友元,B是C的友元,但A不是C的友元
class Time {// 声明Date是Time的友元,但是Time不是Date的友元// Date类中可以访问Time类中的成员,但是Time类中不能访问Date中的成员friend class Date;
public:Time(int hour = 10, int minute = 12, int second = 24):_hour(hour), _minute(minute), _second(second){}
private:int _hour;int _minute;int _second;
};
class Date {
public:Date(int year = 2025, int month = 4, int day = 16):_year(year), _month(month), _day(day) {// 直接在Date类中访问Time类的_hour_t._hour = 0;}void SetTimeOfDate(int hour, int minute, int second) {// 直接访问Time类的成员_t._hour = hour;_t._minute = minute;_t._second = second;}
private:int _year;int _month;int _day;// 在Date类中声明Time类Time _t;
};

五、内部类

  • 一个类定义在另一个类的内部,这个内部的类就称为内部类。内部类是独立的类,仅仅受到类域和访问限定符的限制,所以外部类定义的对象中不包含内部类
  • 内部类是天生的外部类的友元,eg:A类和B类,把A类放入B类,那么A天生是B的友元
  • 内部类本质也是一种封装,如果A和B关系紧密,A实现出来就是给B使用的,而不想让其他类使用A,那么可以考虑把A设计为B的内部类,若放到private或者protected中,那么A就是B的专属内部类,其他类使用不了
class B {
public:// A是B的内部类// 仅仅是将A放到B中,还受到类域和访问限定符的限制class A { // A天生是B的友元private:int a1;};
private:int b1;char b2;
};

相关文章:

  • # 03_Elastic Stack 从入门到实践(三)-- 4
  • 轴映射与轨迹平面(Axis Mapping and Trajectory Planes)
  • AN(G|C)LE as an OpenCL Compute Driver
  • isNaN、Number.isNaN、lodash.isNaN 的区别
  • Python开发一个简单的软件系统
  • 兔子桌面官方下载-兔子桌面TV版-安卓电视版官方免费下载新版
  • 【systemd 写入硬盘大好几个G】
  • docker desktop for windows 登录国内镜像仓库
  • 【Python语言基础】21、Python标准库
  • 黑马点评:Redis消息队列【学习笔记】
  • MyBatis-Plus 详解:快速上手到深入理解
  • 探索大语言模型(LLM):目标、原理、挑战与解决方案
  • 如何用AI辅助数据分析及工具推荐
  • 第七章:7.4写一个函数,使给定的一个3*3的二维整型数组转置,即行列互换。
  • 09-RocketMQ 深度解析:从原理到实战,构建可靠消息驱动微服务
  • 如何用AI辅助软件产品原型设计及工具推荐
  • 【野火模型】利用深度神经网络替代 ELMv1 野火参数化:机制、实现与性能评估
  • ArcGIS Desktop使用入门(四)——9版本与10版本区别
  • 基于Vue Node.js的电影售票网站的设计与实现(源码+lw+部署文档+讲解),源码可白嫖!
  • 人工智能之数学基础:特征值分解与奇异值分解的区别分析
  • 在线购物的网站制作/seo主要做什么
  • 帮客户做网站图片被告侵权/网络科技公司
  • 做网站英文怎么写/洛阳搜索引擎优化
  • 网站建设公司建设/百度登陆页面
  • 帮你做海报网站/深圳公司网络推广该怎么做
  • 企业网站建设需要做哪些工作/太原今日新闻最新头条