【C++学习】类和对象(下)

ops/2024/11/19 23:10:22/

目录

一、再谈构造函数

🍔构造函数体赋值

🍟初始化列表

 二、explicit 关键字

三、static 成员 

🍔概念

🍟特性

四、友员

🍔友员

 🍟友元函数

🌮友元类

五、内部类

🍔概念

六、结语


一、再谈构造函数

🍔构造函数体赋值

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

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

通过构造函数,虽然每个对象都有了一个初始值,但这不是对象中成员变量的初始化构造函数中的语句只能称为赋初值。

为什么这么说呢?

答:初始化只能有一次,而构造函数中可以多次赋值


下面我们就来看看对象中成员变量是如何初始化的⬇️

🍟初始化列表

🐥初始化列表:以一个冒号开始,接着是一个逗号分隔的数据成员列表,每个“成员变量”

面跟一个放在括号里的初始值或表达式

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

初始化列表【❗注意 ❗】

1️⃣每个成员变量只能在初始化列表中出现一次(只能初始一次)

2️⃣尽量使用初始化列表初始化成员变量,因为无论是否使用初始化列表,首先都会用初始化列表初始化

3️⃣成员变量在类中声明的次序就是初始化列表中的初始化顺序,与初始化列表中的先后无关

4️⃣类中包含一下成员,必须放在初始化列表中初始化

        ✅引用成员变量(因为引用必须在定义的时候初始化)

        ✅const成员变量 (因为常量只能初始化,不能赋值)

        ✅自定义类型成员变量(且该类没有默认构造函数)(因为使用初始化列表可以不调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化

//没有默认构造的对象
class A
{
public:A(int a):_a(a){}
private:int _a;
};class B
{
public:B(int a, int ref):_ab(a),_ref(ref),_n(10){}
private:A _ab;       //没有默认构造函数int& _ref;   //引用const int _n;// const
};

 


 

 二、explicit 关键字

如果一个对象的构造函数是单参数,我们可以这样来创建一个对象

class node
{
public:node(int val = 0):_val(val){}
private:int _val;
};int main()
{node d1(1);d1=5;return 0;
}

用一个整形变量给 node类型对象赋值

实际编译器会用 5 构造一个无名对象,然后用无名对象给d1对象赋值

👓当然,我们也可以用explicit关键字禁止这种行为

class node
{
public:explicit node(int val = 0):_val(val){}
private:int _val;
};int main()
{node d1=5;return 0;
}

编译失败:

 


 

三、static 成员 

🍔概念

声明为static的类成员称为类的静态成员

因此有静态成员变量静态成员函数

❗静态成员变量必须在类外进行初始化

class A
{
public:static int GetAcount()//静态成员函数{return _scount;}
private:static int _scount;//必须在类外面进行初始化
};
int A::_scount = 0;

🍟特性

1️⃣静态成员为所有类对象共享,不属于某个具体对象,放在静态区

(也就是说用该类创建的所有对象使用的静态成员都是同一个)


2️⃣静态成员变量必须在类外定义,定义时不需要加static关键字,类中只是声明


3️⃣类静态成员可以用 类名::静态成员对象.静态成员 访问


4️⃣静态成员函数没有隐藏的this指针,不能访问其他非静态成员


5️⃣静态成员也是类的成员,受public、protected、private访问限定符的限制

 

 


 

四、友员

🍔友员

友员提供了一种突破封装的方式,有时提供了便利。但是也会增加耦合度,破坏了封装的意义,所以友员不宜多用。

友员可分为:友元函数  和 友元类

 🍟友元函数

🫗引出:当我们重载operator<<时,如果重载成成员函数,this指针默认就是第一个参数,也就是左操作数,但实际cout才是左操作数。cout<<d1 就会变成 d1<<cout 很奇怪

因此我们只能重载成全局函数,但又会导致类外无法访问类中的成员变量,此时就需要友元来解决⬇️

class Date
{
public:Date(int year = 0, int month = 0, int day = 0):_year(year),_month(month),_day(day){}//如果重载成成员函数//调用时 d1<<cout 不符合我们常规使用//ostream& operator<<(ostream& _cout)//{//    _cout << _year << '-' << _month << '-' << _day;//    return _cout;//}friend ostream& operator<<(ostream& _cout, const Date& d);
private:int _month;int _year;int _day;
};ostream& operator<<(ostream& _cout,const Date&d)
{_cout << d._year << '-' << d._month << '-' << d._day;return _cout;
}

📘【说明】

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

1️⃣友元类可以访问类的私有成员和保护成员,但不是类的成员函数
2️⃣友元函数不能用const修饰
3️⃣友元函数可以在类定义的任何地方声明,不受访问限定符的限制
4️⃣一个函数可以是多个类的友元函数

🌮友元类

友元类可以访问另一个类的所有非公有成员

👉友元关系是单向的

a类可以访问b类的非公有成员变量,但b类不可以访问a类中的非成员变量

👉友元关系不具有传递性

a是b的友员,b是c的友元,但不说明a是c的友元

class A
{
public:A(int a=0):_a(a){}friend class B;
private:int _a;
};class B
{
public:void set_ab(int a, int b){//直接访问A类中的私有成员变量__a._a = a;_b = b;}
private:A __a;int _b;
};


 

 

五、内部类

🍔概念

如果一个类直接定义在另一个类的内部,那么这个类就叫做内部类

内部类是一个独立的类,它不属于外部类,外部类对内部类没有任何访问权限


但内部类是外部类的友元类,内部类可以直接访问外部类的非公有成员

【注意】

1️⃣内部类可以定义在外部类的public、private、protected位置
2️⃣内部类可以直接访问外部类的static成员,不需要外部类的类/对象名
3️⃣sizeof(外部类)=外部类的大小,和内部类无关

class A
{
public:A(int a=0):_a(a){}//内部类class B{public:void set_ab(int a, A& n){//对于static成员不需要加类/对象名k = 0;//可以访问私有成员变量n._a = 0;}};private:static int k;int _a;
};
int A::k = 1;



六、结语

🫡你的点赞和关注是作者前进的动力!

🌞最后,作者主页有许多有趣的知识,欢迎大家关注作者,作者会持续更新有意思的代码,在有趣的玩意儿中成长!


http://www.ppmy.cn/ops/135087.html

相关文章

lab2:docker基础实战

一、实验目的 1.通过本次实验&#xff0c;完成Docker主机的安装和配置、镜像的搜索和下载、容器生命周期的基本管理、容器网络的管理。 2.通过Dockerfile来构建nginx镜像&#xff0c;了解Dockerfile镜像构建过程。 二、实验内容与实验要求 1.完成Docker的安装和配置。 2.完…

电脑Vs台式机 (后续还有)

性能方面&#xff1a; 处理器性能&#xff1a;在相同配置参数下&#xff0c;台式机的处理器性能发挥通常更出色。这是因为台式机的散热条件更好&#xff0c;处理器可以在更稳定的温度下工作&#xff0c;不用担心过热降频等问题。例如&#xff0c;在进行视频编辑、3D 建模等高强…

如何将java项目打包成docker 镜像并且可运行

java 项目打包成 Docker 可运行的镜像&#xff0c;其目的是便于运用docker容器来管理项目。下面是具体的步骤&#xff0c;如果大家遇到啥问题可以留言有空会逐一回复。 目录 1. 确保项目已经打包成 JAR 文件 2. 编写 Dockerfile 3. 构建 Docker 镜像 4. 运行 Docker 容器 …

安全机制解析:深入SELinux与权限管理

Linux内核作为一个高自由度和优秀性能的操作系统核心&#xff0c;基于安全需求提供了完善的安全机制。内核安全机制不仅限于保护个人数据&#xff0c;还包括对运行环境和系统体系的线程化操作。本文将全方位分析Linux内核安全机制&#xff0c;以SELinux为主要代表&#xff0c;选…

Android全局异常捕获

在开发过程中我们会使用try{}catch捕获一些异常&#xff0c;不过我们毕竟不能面面俱到&#xff0c;所以总会有一些异常在我们想不到的位置发生&#xff0c;然后程序就崩溃了&#xff0c;于是赶紧连上电脑复现bug&#xff0c;有的可以复现有的一时还复现不了&#xff0c;然后就各…

hive 统计各项目下排名前5的问题种类

实现指定某项目下的数据效果图如下所示&#xff1a; 其中 ABCDE 为前5名的问题种类&#xff0c;其中A问题有124个&#xff08;出现了124次&#xff09; 数据说明&#xff1a; 整个数据集 包含很多项目一个项目 包含很多问题一个问题 选项 可认为是 类别值&#xff0c;所有出…

RK3568硬解码并与Qt界面融合显示深入探究

1. 最近实在头疼&#xff0c;因为项目换了平台。折腾来折腾去&#xff0c;到今天算是把很多坑踩完了。 RK上实现硬解码方案一共有一下几种方式 1&#xff09;opencvgstreamer插件&#xff0c;采用硬解码&#xff0c;只能解码出图像&#xff0c;无法解出声音 2&#xff09;ff…

Windows C++ TCP/IP 两台电脑上互相传输字符串数据

在 Windows 上使用 C 实现两个进程通过 TCP/IP 协议传输字符串数据是一个非常常见的任务。我们可以利用 Windows Sockets API (winsock2) 来进行套接字编程。在下面的例子中&#xff0c;我们将演示如何通过 TCP/IP 协议传输字符串数据。这里将包括两个程序&#xff1a;一个是服…