【C++】类和对象的知识点

目录

一,初始化列表

二,static静态成员

三,友元

3-1,友元函数

3-2,友元类   

四,内部类

五,匿名对象


一,初始化列表

引入:

        在谈初始化列表前,我们先清楚的认识下构造函数。构造函数的定义是在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值,这里要注意的是,造函数调用之前,对象中已经有了一个初始值。也就是说构造函数体中的语句只能将其称为赋初值,而不能将其称为对象中成员变量的初始化,因为初始化是在建立时给予初值,而构造函数体内可以多次赋值。        

        在类对象中,对其成员变量进行初始化的操作叫初始化列表,初始化列表是一种用于初始化成员变量的语法结构,它在类的构造函数中使用,用于初始化类的成员变量。总的来说,初始化列表就是类成员变量的初始化。

定义:

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

class Date
{
public:
    Date(int year, int month, int day)
        //初始化列表,对成员变量进行初始化
        :_year(year)
        ,_month(month)
        ,_day(day)
    {
        //...这里进行赋值操作
    }
private:
    int _year;
    int _month;
    int _day;
};

初始化列表需注意以下几个要点:

        1,每个成员变量在初始化列表中只能出现一次,因为初始化只能初始化一次。

        2,类中包含以下成员,必须放在初始化列表位置进行初始化,不能调用构造函数:               

                (1)引用成员变量。因为引用必须初始化,且一旦初始化后就不能改变,构造函数                  等于赋值操作。

                (2)const成员变量。const修饰的变量不能改变,与引用成员变量同理。

                (3)自定义类型成员(且该类没有默认构造函数时)。自定义类型运用初始化列表,相当            于直接给自定义类型直接赋值。相当于从内置类型转换成自定义类型(后面会详细讲解)。

class A
{
public:
    A(int a = 6, int b = 5) //自己定义构造函数,编译器不会自动产生默认构造函数
        :_a(a)
        , _b(b)
    { /* ....... */ }
private:
    int _a;
    int _b;
};
class B
{
public:
    B(int a = 1, int b = 1)
        :_aobj(a) //相当于隐式类型的转换
        ,_ref(b)
        ,_n(10)
    { /* ....... */ }
private:
    A _aobj;  // 没有默认构造函数
    int& _ref;  // 引用
    const int _n; // const
};
int main()
{
    B a(5);
    return 0;
}

        3,因为初始化列表相当于初始化,所以初始化列表在变量定义时就调用。

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

class Date
{
public:
    Date(int year = 2023, int month = 10, int day = 16)
        //在编译器调用时依次调用_year,_month,_day,按照声明顺序调用
        : _month(month)
        , _day(day)
        , _year(year)
    {   }
private:
    int _year;
    int _month;
    int _day;
};

       这方面也经常会让我们运用,请观看以下代码:

#include <iostream>
using namespace std;
class A
{
public:A(int a):_a1(a), _a2(_a1){}void Print() {cout << _a1 << " " << _a2 << endl;//输出1和随机值}
private:int _a2;//先调用初始化列表中的_a2int _a1;//再调用初始化列表中的_a1
};
int main() {A aa(1);aa.Print();
}

        其实理解起来也非常简单,初始化列表是给变量初始化,在变量声明时就要开始赋值,因此,初始化列表是按照变量声明的顺序进行的。

        下面,要说明的是在构造函数中不能只要初始化列表,不要函数体初始化,因为有些初始化或者检查工作,初始化列表也不能全部解决,如下:

class Stack
{
private:
    Stack(int capacity = 5)
        : _capacity(capacity)
        , _top(-1)
    {
        //a初始化时要进行检查工作,在初始化列表中不能完成
        a = new int[capacity];
        if (a == nullptr) {
            perror("malloc fial");
            exit(-1);
        }
    }
private:
    int* a;
    int _capacity;
    int _top;
};

总:通过以上学习可看出,初始化列表也不能解决全部问题,在后面的学习和深入探索中,初始化列表和构造函数实体往往是混合使用的。


二,static静态成员

概念:

        声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用 static修饰的成员函数,称之为静态成员函数。

注意:

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

        2,静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区,可用sizeof关键字进行查看。

class Date1 //占12个字节
{
    int _year;
    int _month;
    int _day;
    static int _a;
};
class Date2 //占16个字节
{
    int _year;
    int _month;
    int _day;
    int _a;
};

        3,静态成员变量必须在类外进行初始化和定义,定义时不添加static关键字,类中只是声明。因为静态成员没有存储在类中,存储在静态区中,不能对其进行类中的操作。

class Date1
{
public:
    Date1(int year = 2023, int month = 10, int day = 16)
        : _year(year)
        , _month(month)
        , _day(day)
        //, _a(2)错误,因为静态成员变量没有存储在类中
    {     }
    int _year;
    int _month;
    int _day;
    static int _a;
};
int Date1::_a = 5;//对静态成员变量进行初始化

        4,类静态成员即可用类名::静态成员或者对象.静态成员来访问,但这两种方法访问的权限必须为公有。用类的成员函数也可间接访问,这种方法可间接的在类外访问私有权限的成员。

#include <iostream>
using namespace std;
class Date1
{
public:Date1(int year = 2023, int month = 10, int day = 16): _year(year), _month(month), _day(day){       }int GetData() {return _a;}int _year;int _month;int _day;static int _a;
};
int Date1::_a = 5;
int main()
{Date1 d1;cout << d1._a << endl;//权限必须公有cout << Date1::_a << endl;//权限必须公有cout << d1.GetData() << endl;//即使权限私有也可访问return 0;
}

        5,静态成员函数没有隐藏的this指针,不能访问任何非静态成员,但可以访问静态成员,因为访问类中非静态成员需要this指针来 “指引” ,而静态成员存储在静态区中,可以随时访问。

class Date1
{
public:
    Date1(int year = 2023, int month = 10, int day = 16)
        : _year(year)
        , _month(month)
        , _day(day)
    {       }
    static int GetData()
    {
        //return _year;//没有this指针,找不到此对象
        return _a;//_a为静态成员,不在类中,可以访问
    }
    int _year;
    int _month;
    int _day;
    static int _a;
};

        这里要说明的是静态成员函数不可以调用非静态成员函数,但非静态成员函数可以调用类的静态成员函数。静态成员函数由于没有this指针,不能访问类中成员,静态成员函数跟静态成员变量一样,都存储在静态区中,所以可以任意访问。


三,友元

       在C++中,友元是一个关键字,它用于允许一个类的成员函数访问另一个类的私有和保护成员。使用友元函数或友元类,可以访问一个类的私有和保护成员,就像它们是公共成员一样。其中友元共分为:友元函数友元类

3-1,友元函数

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

class Date
{
    //友元函数的声明
    friend ostream& operator<<(ostream& _cout, const Date& d);
    friend istream& operator>>(istream& _cin, Date& d);
public:
    Date(int year = 2023, int month = 10, int day = 16)
        : _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 >> d._month >> d._day;//访问类中的私有成员变量
    return _cin;
}

这里要说明以下几点:

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

        2,友元函数不能用const修饰。

        3,友元函数可以在类定义的任何地方声明,不受类访问限定符限制。

3-2,友元类   

        在C++中,友元类是一种特殊的关系,它允许一个类访问另一个类的私有和保护成员。使用友元类,可以访问一个类的私有和保护成员,就像它们是公共成员一样。

        要声明一个类为另一个类的友元类,可以在类定义中加入friend关键字,并使用类名作为友元类的声明。

class Time
{
    // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成员变量
    friend class Date;  
    int _hour;
    int _minute;
    int _second;
};
class Date
{
public:
    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;
};


四,内部类

概念:

        如果一个类定义在另一个类的内部,那么这个定义在内部的类就叫做内部类。内部类是一个独立的类, 它不属于外部类,更不能通过外部类的对象去访问内部类的成员,即外部类不是内部类的友元,但内部类是外部类的友元类,即内部类可以通过外部类的对象参数来访问外部类中的所有成员。

注意:

        1,内部类可以直接访问外部类中的静态成员,不需要外部类的对象/类名。

        2,定义内部类时不能直接定义,需要外部类来限定域的作用空间。

#include <iostream>
using namespace std;
class A
{
private:static int k;int h;
public:class B // B天生就是A的友元{public:void fun(const A& a){//这里要说明的是内部类可以直接访问外部类中的静态成员,不需要外部类的对象/类名cout << k << endl;//直接访问静态成员cout << a.h << endl;//访问A类中的私有成员}};
};
int A::k = 1;
int main()
{A::B b;//定义内部类对象breturn 0;
}

五,匿名对象

概念:在类中,我们可以对类进行不取名字的方式定义,这种定义对象的方式叫做匿名对象。其中,匿名对象的生命周期只有这一行,当这一行结束时将会自动调用析构函数。

        匿名对象在只需使用一次的场合下非常好用,这里我们先了解一下,后面的文章将会深入展开这一方面。使用如下:

#include <iostream>
using namespace std;
class A
{
public:A(int a = 0):_a(a){   }~A(){cout << "~A()" << endl;}int GetData() {return _a;}
private:int _a;
};;
int main()
{A();//建立匿名对象,这一行结束后将调用析构函数A().GetData();//使用匿名对象调用成员函数,结束后将自动调用析构函数return 0;
}

总:本章节只是初步学习类与对象中的知识点,具体的深入探索到了后面会详细讲解,这里我们只需先理解并会用即可。

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

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

相关文章

反渗透水处理成套设备有哪些

反渗透水处理成套设备主要包括反渗透装置、预处理系统、控制系统等部分。 反渗透装置&#xff1a;反渗透水处理设备的核心部分&#xff0c;由反渗透膜、压力容器、膜组件等组成。反渗透膜是一种高分子材料制成的半透膜&#xff0c;能够截留水中的溶解盐、有机物、细菌等杂质&a…

(动手学习深度学习)第13章 计算机视觉---微调

文章目录 微调总结 微调代码实现 微调 总结 微调通过使用在大数据上的恶道的预训练好的模型来初始化模型权重来完成提升精度。预训练模型质量很重要微调通常速度更快、精确度更高 微调代码实现 导入相关库 %matplotlib inline import os import torch import torchvision f…

Midjourney绘画提示词Prompt参考学习教程

一、工具 SparkAi&#xff1a; SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软…

SDL2 播放音频数据(PCM)

1.简介 这里以常用的视频原始数据PCM数据为例&#xff0c;展示音频的播放。 SDL播放音频的流程如下&#xff1a; 初始化音频子系统&#xff1a;SDL_Init()。设置音频参数&#xff1a;SDL_AudioSpec。设置回调函数&#xff1a;SDL_AudioCallback。打开音频设备&#xff1a;SD…

ML-Net:通过深度学习彻底改变多标签分类

一、说明 多标签分类是一项具有挑战性的机器学习任务&#xff0c;其中输入可以同时属于多个类。传统的多标签分类方法通常依赖于将问题转化为一系列二元分类任务或使用集成方法。然而&#xff0c;深度学习的出现开创了多标签分类的新时代&#xff0c;ML-Net 等模型突破了该领域…

02-1解析xpath

我是在edge浏览器中安装的xpath&#xff0c;需要安装的朋友可以参考下面这篇博客最新版edge浏览器中安装xpath插件 一、xpathd的使用 安装lxml pip install lxml ‐i https://pypi.douban.com/simple导入lxml.etree from lxml import etreeetree.parse() 解析本地文件 htm…

SpringBoot和Spring的区别是什么?

目录 Spring SpringBoot 区别&#xff1a; 1、自动配置: 2、内嵌Web服务器: 3、约定大于配置: Spring Spring是一个非常强大的企业级Java开发框架&#xff0c;Spring 框架为开发 Java 应用程序提供了全面的基础架构支持。它包含一些很好的功能&#xff0c;如依赖注入和开…

vscode的git 工具使用

vscode的git 工具使用 目录概述需求&#xff1a; 设计思路实现思路分析1.git 工具的使用2.提交代码3.查看历史提交代码 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a be…

使用webhook发送企业微信消息

文章目录 使用webhook发送企业微信消息企业微信群机器人思路实现总结 使用webhook发送企业微信消息 企业微信群机器人思路实现 1&#xff0c;在企业微信中新建一个群 2&#xff0c;在设置里面添加机器人 3&#xff0c;拿到webhook地址 在终端某个群组添加机器人之后&#xf…

Servlet API 详解

文章目录 前言什么是ServletHttpServletHttpServletRequest1. form表单构造POST请求2. JSON形式表示body部分 HttpServletResponse 前言 前面为大家介绍了如何使用 servlet 写一个简单的网站&#xff0c;前面只是大概了解了如何使用简单的 servlet&#xff0c;而平时网站的逻辑…

Hive Lateral View explode列为空时导致数据异常丢失

一、问题描述 日常工作中我们经常会遇到一些非结构化数据&#xff0c;因此常常会将Lateral View 结合explode使用&#xff0c;达到将非结构化数据转化成结构化数据的目的&#xff0c;但是该方法对应explode的内容是有非null限制的&#xff0c;否则就有可能造成数据缺失。 SE…

一体多面:哪有什么DO、BO、DTO,只不过是司空见惯的日常

欢迎大家关注公众号「JAVA前线」查看更多精彩分享文章&#xff0c;主要包括源码分析、实际应用、架构思维、职场分享、产品思考等等&#xff0c;同时欢迎大家加我微信「java_front」一起交流学习 1 分层疑问 无论DDD还是MVC模式构建项目&#xff0c;势必涉及到工程结构的分层&…

typora整理markdown笔记

效果 符号 快捷键 斜体 * * ctrlB(代表同时按) 加粗 ** ** ctrlI 竖线 > 超链接 清除样式 ctrl\ 图片 ![图片描述][图片绝对路径/相对路径] 如何在Typora中插入图像&#xff1f; ➊ 使用Markdown语法 &#xff08;不推荐&#xff0c;太慢&#xff09; ➋ 直接拷贝图…

Theory behind GAN

假如要生成一些人脸图&#xff0c;实际上就是想要找到一个分布&#xff0c;从这个分布内sample出来的图片像是人脸&#xff0c;分布之外生成的就不像人脸。而GAN要做的就是找到这个distribution。 在GAN之前用的是Maximum Likelihood Estimation。 Maximum Likelihood Estimat…

同创永益联合红帽打造一站式数字韧性解决方案

随着AI技术的快速兴起&#xff0c;IT技术已成为推动业务持续增长的重要驱动力&#xff0c;这要求企业不断尝试新事物&#xff0c;改变固有流程&#xff0c;加强IT技术与业务的合作&#xff0c;同时提升数字韧性能力&#xff0c;以实现业务目标。10月26日&#xff0c;红帽2023中…

Bert学习笔记(简单入门版)

目 录 一、基础架构 二、输入部分 三、预训练&#xff1a;MLMNSP 3.1 MLM&#xff1a;掩码语言模型 3.1.1 mask模型缺点 3.1.2 mask的概率问题 3.1.3 mask代码实践 3.2 NSP 四、如何微调Bert 五、如何提升BERT下游任务表现 5.1 一般做法 5.2 如何在相同领域数据中进…

学习UI第一天

在工作闲暇之余&#xff0c;自己画的原型图&#xff0c;再次做一次记录&#xff0c;哈哈哈 萌宠领养UI设计原型图 https://modao.cc/proto/lq2KqIVBs48xwylNZlA7OP/sharing?view_moderead_only #萌宠领养-分享 可以点击此链接&#xff0c;进行查看O(∩_∩)O哈哈~

基于uni-app的汽车租赁app的设计与实现

1.项目背景及意义 项目背景&#xff1a; 随着人们生活水平的提高&#xff0c;汽车租赁服务在城市中变得越来越普及。传统的租车方式存在一些问题&#xff0c;比如租车流程繁琐、费用不透明、选择有限等。因此&#xff0c;开发一款基于uni-app的汽车租赁app成为了满足用户需求…

基于RFID的自动化仓储设备研发项目可行性研究报告

一、项目概况 基于RFID的自动化仓储设备研发项目&#xff0c;是深圳市飞鸟国际供应链股份有限公司在公司有色金属供应链一站式服务的基础上&#xff0c;针对有色金属供应链的仓储环节进行的研发。 多年来&#xff0c;公司一直坚持以“科技金融”为核心的未来发展战略&#xf…

二进制部署k8s集群-过程中的问题总结(接上篇的部署)

1、kube-apiserver部署过程中的问题 kube-apiserver.conf配置文件更改 2、calico的下载地址 curl https://docs.projectcalico.org/v3.20/manifests/calico.yaml -O 这里如果kubernetes的节点服务器为多网卡配置会产生报错 修改calino.yaml配置文件 解决方法&#xff1a; 调…