C++基础知识(四:类的学习)

类指的就是对同一类对象,把所有的属性都封装起来,你也可以把类看成一个高级版的结构体。

【1】定义

class 类名
{
访问权限:
    成员属性;
访问权限:
    成员方法;
}访问权限:
public:共有的,类内、类外和子类中都可以访问
private:私有的,类内可以访问,类外和子类中都不能访问,类中默认是私有权限
protected:受保护的,类内和子类中可以访问,类外不可以访问(继承再说)访问权限,是针对于一个类来说的

【2】类和结构体的区别

  1. 类的封装性比结构体更好,类中默认是私有权限,结构体中默认是共有权限
  2. 结构体默认是公有继承,类默认是私有继承
  3. C++中类就是由结构体演变来的
  4. 结构体一般用于实现某种数据结构时,类一般用于描述一类对象的性质

【3】this指针**

每一个类中的非静态成员函数,都有一个this指针,指向调用者,(非静态成员数隐藏 的形参)

谁调用this就指向谁哪一个类对象调用成员函数,就会用该类对象的首地址,初始化形参this

原型:类类型  *const this; ----->指针的指向不能修改

需要使用this指针的场合

  1. 当形参和成员属性同名
  2. 拷贝赋值函数,需要返回自身的引用
#include <iostream>using namespace std;
class Rec
{
private:int len;int wid;
public:void set(int l,int w);  //设置长和宽void show();   //输出面积和周长int get_l();     //获取长和宽int get_wid();
};void Rec::set(int len, int wid)   //r1.set()
{this->len = len;this->wid = wid;
}void Rec::show()
{
    cout << "周长:" << (len+wid)*2 << endl;
    cout << "面积:" << len*wid << endl;
}int Rec::get_l()
{return len;
}int Rec::get_wid()
{return wid;
}
int main()
{
    Rec r1;  //r1是一个类对象,实例化了一个类对象r1
    r1.set(9,2);
    Rec r2;
    r2.set(9,2);
    cout << "&r1=" << &r1 << endl;return 0;
}

【4】类中的特殊成员函数

特殊的构造函数都是public权限

类中,会默认提供一些特殊的成员函数:构造函数、析构函数、拷贝构造函数、拷贝赋值函数

【5】构造函数

构造函数支持函数重载

构造函数,会在实例化类对象时,系统默认调用无参构造;

如果用户手动定义出了构造函数,系统将不再提供构造函数

类名()
{//函数体
}

调用时机

栈区:实例化类对象时,自动调用

堆区:什么时候使用new申请空间,什么时候调用构造函数

当提供构造函数后

ii)构造函数提供了初始化列表的机制

如果在函数体内部,给成员属性赋值,是一个赋值的过程,不是初始化的过程

类名():成员属性1(形参的值1),成员属性2(形参的值)`````在函数头后面,使用:引出初始化列表,每个成员属性以,分隔,()里面是形参,外面是成员属性

iii)需要使用初始化列表的情况

  1. 形参和成员属性同名
  2. 类中有引用成员时,必须使用初始化列表
#include <iostream>using namespace std;
class Stu
{int age;float high;int &score;
public://构造函数支持函数重载Stu(int age,float high,int a):age(age),high(high),score(a){
        cout << "Stu的有参构造" << endl;}
};int main()
{//Stu s;int n1 = 90;
    Stu s1(18,9,n1);    //在栈区
    Stu *p;//p = new Stu;   //在堆区申请了Stu类对象的空间return 0;
}
  1. 类中有const修饰的成员时,必须使用初始化列表
#include <iostream>using namespace std;
class Stu
{int age;float high;const int score;
public:
//    Stu()
//    {
//        cout << "Stu的无参构造函数" << endl;
//    }//构造函数支持函数重载Stu(int age,float high,int a):age(age),high(high),score(a){
        cout << "Stu的有参构造" << endl;}
};int main()
{//Stu s;int n1 = 90;
    Stu s1(18,9,89);    //在栈区
    Stu *p;//p = new Stu;   //在堆区申请了Stu类对象的空间return 0;
}
  1. 类中含有其他类的子对象时,必须使用初始化列表(类的包含关系)

(如果另一个类只有有参构造需要在初始化列表中宏显性调用,如果另一个类有无参构造,可以不写初始化列表)

                类的包含关系

#include <iostream>using namespace std;
class Per
{
    string name;
public:Per(string name){this->name = name;
        cout << "Per的有参构造" << endl;}
};class Stu
{int age;float high;int score;
    Per p1;   //Per类只有有参构造函数
public:Stu():p1("zhangsan"){
        cout << "Stu的无参构造函数" << endl;}//构造函数支持函数重载Stu(int age,float high,int a,string name):p1(name){this->age = age;this->high = high;this->score = a;
        cout << "Stu的有参构造" << endl;}
};int main()
{
    Stu s;int n1 = 90;
    Stu s1(18,9,89,"lisi");    //在栈区return 0;
}

【6】析构函数

不支持函数重载

在类对象空间消亡时,系统自动调用

i)格式

~类名()
{//函数体
}

ii)调用时机

栈区:对象消亡时,自动调用
堆区:什么时候delete,什么时候调用

构造函数和析构函数调用的时机:

先构造的后析构,后构造的先析构

iii)需要显性写出析构函数的场景

类中有指针成员,并且指针成员,指向堆区的空间

#include <iostream>using namespace std;
class Stu
{
    string name;int *p;
public:Stu():p(new int)   //保证指针成员,指向堆区的空间{
        cout << "堆区申请的空间为:" << p << endl;
        cout << "Stu的无参构造" << endl;}
//    Stu(string name,int p):name(name),p(new int(p))
//    {
//        cout << "Stu的有参构造" << endl;
//    }~Stu(){
        cout << "准备释放堆区的空间:" << p << endl;delete p;
        cout << "Stu的析构函数" << endl;}};int main()
{
    Stu s1;return 0;
}

【7】拷贝构造函数

利用一个类对象,给另一个类对象初始化时,自动调用拷贝构造函数

如果自己实现了拷贝构造,系统不再提供默认的拷贝构造

i)格式

类名(同类对象的引用)
{
   //函数体
}

ii)使用

#include <iostream>using namespace std;
class Per
{
    string name;
public://Per中,自己定义了有参构造,系统不再提供无参构造Per(string name){this->name = name;
        cout << "Per的有参构造" << endl;}~Per(){
        cout << "Per的析构函数" << endl;}
};class Stu
{int age;float high;int score;//Per p1;   //Per类只有有参构造函数
public:Stu(){
        cout << "Stu的无参构造函数" << endl;}//构造函数支持函数重载Stu(int age,float high){this->age = age;this->high = high;
        cout << "Stu的有参构造" << endl;}//拷贝构造Stu(Stu &other){//this->age = other.age;this->high = other.high;
        cout << "拷贝构造函数" << endl;}~Stu(){
        cout << "Stu的析构函数" << endl;}void show();
};
void Stu::show()
{
    cout << "age = " << age << endl;
    cout << "high = " << high << endl;
}
int main()
{
    Stu s1(19,100);
    cout << "s1的show:" << endl;
    s1.show();
    Stu s2=s1;
    cout << "s2的show:" << endl;
    s2.show();return 0;
}

iii)深浅拷贝问题**

当类中有指针成员,会涉及到深浅拷贝问题

浅拷贝:两个不同类对象的指针成员,指向同一片空间

问题:析构时,会发生二次释放问题;同一片空间被两个不同的类对象占用,发生资源抢占

深拷贝:两个不同类对象的指针成员,指向不同的空间,但是保存的是同样的数据

浅拷贝

深拷贝

#include <iostream>using namespace std;
class Stu
{
    string name;int *p;
public:Stu():p(new int)   //保证指针成员,指向堆区的空间{
        cout << "堆区申请的空间为:" << p << endl;
        cout << "Stu的无参构造" << endl;}Stu(string name,int p):name(name),p(new int(p)){}~Stu(){
        cout << "准备释放堆区的空间:" << p << endl;delete p;        cout << "Stu的析构函数" << endl;}//使用同类其他对象的指针成员解引用后的值,给自己的指针成员的内容初始化Stu(Stu &other):name(other.name),p(new int(*(other.p))){/*this->name = other.name;
        this->p = new int(*(other.p));*/
        cout << "Stu的拷贝构造" << endl;}void show();
};
void Stu::show()
{
    cout << "name= " << name << endl;
    cout << "p= " << p << endl;
    cout << "*p= " << *<< endl;
}
int main()
{
    Stu s1("zhangsan",18);
    cout << "s1的show:" << endl;
    s1.show();
    Stu s2 = s1;
    cout << "s2的show:" << endl;
    s2.show();return 0;
}

iv)拷贝构造函数的调用时机

  1. 使用已有的类对象,给新的类对象初始化
  2. 函数的参数是一个类对象时,也会调用拷贝构造函数
  3. 函数的返回值是一个类对象时,也会调用拷贝构造函数

测试代码:

#include <iostream>using namespace std;
class Stu
{
    string name;
public:Stu(){
        cout << "Stu的无参构造" << endl;}Stu(Stu &other):name(other.name){
        cout << "Stu的拷贝构造函数" << endl;}Stu(string name):name(name){
        cout << "Stu的右参构造" << endl;}
};Stu fun(Stu s1)
{return s1;
}
int main()
{
    Stu s;//Stu s2(fun(s));   //会报错,因为fun(s)的返回值是一个临时值,不能引用return 0;
}

【8】拷贝赋值函数 

使用已有的类对象,给另外一个已有的类对象赋值

系统默认提供一个拷贝赋值函数

本质:赋值运算符的重载

i)格式

类名 &operator=(const 类名&other)
{
  //函数体
}

ii)代码

 #include <iostream>using namespace std;
class Stu
{
    string name;int *p;
public://深拷贝赋值函数
    Stu &operator=(const Stu &other){
        name = other.name;*= *(other.p);
        cout << "Stu的拷贝赋值函数" << endl;return *this;}Stu():p(new int)   //保证指针成员,指向堆区的空间{
        cout << "堆区申请的空间为:" << p << endl;
        cout << "Stu的无参构造" << endl;}Stu(string name,int p):name(name),p(new int(p)){}~Stu(){
        cout << "准备释放堆区的空间:" << p << endl;delete p;        cout << "Stu的析构函数" << endl;}//使用同类其他对象的指针成员解引用后的值,给自己的指针成员的内容初始化Stu(Stu &other):name(other.name),p(new int(*(other.p))){/*this->name = other.name;
        this->p = new int(*(other.p));*/
        cout << "Stu的拷贝构造" << endl;}void show();
};
void Stu::show()
{
    cout << "name= " << name << endl;
    cout << "p= " << p << endl;
    cout << "*p= " << *<< endl;
}
int main()
{
    Stu s1("zhangsan",18);
    cout << "s1的show:" << endl;
    s1.show();
    Stu s2;
    s2 = s1;
    cout << "s2的show:" << endl;
    s2.show();return 0;
}

【9】匿名对象

没有对象名,通过类名实例化出来的对象,类名();

Stu();生命周期更短

  1. 全局函数传参
  2. 类数组赋值     //int a=9,b=7,c=8;    int arr[3]={a,b,c};   //int arr[3]={9,7,8};
  3. 临时调用类中的成员函数
  4. 给新的类对象赋值
#include <iostream>using namespace std;
class Stu
{
    string name;int *p;
public://深拷贝赋值函数
    Stu &operator=(const Stu &other){
        name = other.name;*= *(other.p);
        cout << "Stu的拷贝赋值函数" << endl;return *this;}Stu():p(new int)   //保证指针成员,指向堆区的空间{
        cout << "堆区申请的空间为:" << p << endl;
        cout << "Stu的无参构造" << endl;}Stu(string name,int p):name(name),p(new int(p)){}~Stu(){
        cout << "准备释放堆区的空间:" << p << endl;delete p;        cout << "Stu的析构函数" << endl;}//使用同类其他对象的指针成员解引用后的值,给自己的指针成员的内容初始化Stu(const Stu &other):name(other.name),p(new int(*(other.p))){/*this->name = other.name;
        this->p = new int(*(other.p));*/
        cout << "Stu的拷贝构造" << endl;}void show();
};
void Stu::show()
{
    cout << "name= " << name << endl;
    cout << "p= " << p << endl;
    cout << "*p= " << *<< endl;
}void fun(Stu s1)
{
    cout << "调用成功" << endl;
}
int main()
{//1、使用匿名对象用做全局函数传参fun(Stu());   //匿名对象的生命周期,只在定义语句的位置,是一个临时值//2、想要临时使用类中的成员函数Stu().show();//3、给类对象的数组赋值
    Stu arr[3]={Stu("zhangsan",8),Stu("lisi",19),Stu("xiaoming",20)};//4、给新的类对象赋值
    Stu s3(Stu("zhangsan",18));return 0;
}

【10】C++中结构体和C的区别以及C++中结构体和类的区别

  1. C中定义需要加struct,C++中可以不加struct
  2. C++中结构体可以有访问权限的控制(public、private、protected)
  3. C++中结构体可以继承
  4. C++中结构体可以封装函数
  5. C++中结构体内可以定义另外一个结构体声明(类型)

结构体和类的区别:

  1. 使用场合不同,类适用于某一类对象属性和方法的封装,结构体用于某种数据结构的实现
  2. 类中默认private,结构体中默认是public
  3. 类默认是私有继承,结构体默认是共有继承
  4. 类的封装性比结构体的封装性更好

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

接近于pi的程序

在一个平静的午后&#xff0c;两个神秘的数字悄然相遇了。它们分别是-1031158223和-328227871。这两个数字看起来普普通通&#xff0c;但谁知它们背后隐藏着一段令人惊叹的奇幻之旅。 这两个数字其实是π的两位探险家&#xff0c;它们决定通过一次除法运算来探索π的奥秘。它们…

怎么在线生成动态gif?这个网站一定要知道

静态图片是指一张固定的、不具有动态效果的图片。它通常是由像素点组成的&#xff0c;可以是照片、插图、图标等。静态图片只能呈现一种特定的场景或图像&#xff0c;不能展示动态变化。动态图片&#xff08;是由一系列静态图片组成的&#xff0c;通过快速连续播放这些画面&…

线程共享和非共享的资源及线程优缺点

注意&#xff1a;共享的内存地址空间中不包括栈&#xff1b;共享文件描述符表&#xff0c;表示&#xff0c;同一进程中线程可以操作同一文件。

使用代理IP技术实现爬虫同步获取和保存

概述 在网络爬虫中&#xff0c;使用代理IP技术可以有效地提高爬取数据的效率和稳定性。本文将介绍如何在爬虫中同步获取和保存数据&#xff0c;并结合代理IP技术&#xff0c;以提高爬取效率。 正文 代理IP技术是一种常用的网络爬虫技术&#xff0c;通过代理服务器转发请求&a…

力扣 48. 旋转图像

1.题目 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]]…

探索设计模式的魅力:状态模式揭秘-如何优雅地处理复杂状态转换

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;并且坚持默默的做事。 探索设计模式的魅力&#xff1a;状态模式揭秘-如何优雅地处理复杂状态转换 文章目录 一、案例…

HCIA-HarmonyOS设备开发认证V2.0-IOT硬件子系统-WatchDog

目录 一、 WATCHDOG 概述功能简介基本概念 二、WATCHDOG 模块相关API三、WATCHDOG HDF驱动开发3.1、开发步骤(待续...) 坚持就有收获 一、 WATCHDOG 概述 功能简介 看门狗&#xff08;Watchdog&#xff09;&#xff0c;又称看门狗计时器&#xff08;Watchdog timer&#xff0…

零基础学编程,编程简单学,中文编程工具下载及工具箱进度条构件的用法

一、前言 今天给大家分享的中文编程开发语言工具 进度条构件的用法。 编程入门视频教程链接 https://edu.csdn.net/course/detail/39036 编程工具及实例源码文件下载可以点击最下方官网卡片——软件下载——常用工具下载——编程工具免费版下载及实例源码下载。 进度条 进度…

涵盖5大领域的机器学习工具介绍

随着数据的产生及其使用量的不断增加&#xff0c;对机器学习模型的需求也在成倍增加。由于ML系统包含了算法和丰富的ML库&#xff0c;它有助于分析数据和做出决策。难怪机器学习的知名度越来越高&#xff0c;因为ML应用几乎主导了现代世界的每一个方面。随着企业对这项技术的探…

信息检索(二):Dense Passage Retrieval for Open-Domain Question Answering

Dense Passage Retrieval for Open-Domain Question Answering 摘要1. 引言2. 背景3. DPR4. 实验设置5. 实验&#xff1a;文章检索6. 实验&#xff1a;问题问答7. 相关工作8. 结论参考资料 原文链接&#xff1a;https://aclanthology.org/2020.emnlp-main.550.pdf DPR 最早引入…

六、回归与聚类算法 - K-means算法

目录 1、K-means 聚类步骤 2、API 3、案例 4、性能评估指标 5、总结 线性回归欠拟合与过拟合线性回归的改进 - 岭回归分类算法&#xff1a;逻辑回归模型保存与加载无监督学习&#xff1a;K-means算法 1、K-means 聚类步骤 2、API 3、案例 4、性能评估指标 5、总结

【数据结构与算法初学者指南】【冲击蓝桥篇】String与StringBuilder的区别和用法

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《数据结构与算法&#xff1a;初学者入门指南》&#x1f4d8;&am…

【 JS 进阶 】Web APIs (一)

“生命是一曲奇妙的交响&#xff0c;每一段都是挑战&#xff0c;每一个音符都是机遇。在激情的旋律中&#xff0c;用勇气弹奏&#xff0c;创造出属于自己的华彩人生。” - 贝多芬 了解 DOM 的结构并掌握其基本的操作&#xff0c;体验 DOM 的在开发中的作用 知道 ECMAScript 与 …

基于SpringBoot的家教管理系统

基于SpringBootVue的家教管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatis工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 前台主页 家教 个人中心 管理员界面 摘要 本文介绍了基于SpringBoot框架开发的家…

【深度学习笔记】3_5 图像分类数据集fashion-mnist

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 3.5 图像分类数据集&#xff08;Fashion-MNIST&#xff09; 在介绍softmax回归的实现前我们先引入一个多类图像分类数据集。它将在后面的章节中被多次使用&#xff0c…

论文是怎么一回事

最近找到女朋友了&#xff0c;她还挺关心我毕业和论文的事情&#xff0c;我开始着手弄论文了~ 说来惭愧&#xff0c;我一直以为读研就是做东西当作工作来完成&#xff0c;结果一直陷入如何实现的问题&#xff0c;结果要论文时不知道怎么弄创新点&#xff0c;这才转过头来弄论文…

信号系统之线性图像处理

1 卷积 图像卷积的工作原理与一维卷积相同。例如&#xff0c;图像可以被视为脉冲的总和&#xff0c;即缩放和移位的delta函数。同样&#xff0c;线性系统的特征在于它们如何响应脉冲。也就是说&#xff0c;通过它们的脉冲响应。系统的输出图像等于输入图像与系统脉冲响应的卷积…

重点媒体如何投稿?考核稿件投稿指南

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 机构组织&#xff0c;国企央企都需要定期将相关新闻投递到央媒&#xff0c;官媒&#xff0c;或者地方重点媒体中&#xff0c;那么如何进行投稿了&#xff0c;今天就与大家分享下。 央媒投…

喝多少瓶汽水

喝多少瓶汽水 题目描述&#xff1a;解法思路&#xff1a;解法代码&#xff1a;运行结果: 题目描述&#xff1a; 水已知1瓶汽水1元&#xff0c;2个空瓶可以换⼀瓶汽水&#xff0c;输入整数n&#xff08;n>0&#xff09;&#xff0c;表示n元钱&#xff0c;计算可以多少汽水&a…

《Docker 简易速速上手小册》第2章 容器和镜像(2024 最新版)

文章目录 2.1 理解 Docker 容器2.1.1 重点基础知识2.1.2 重点案例&#xff1a;使用 Docker 运行 Python 应用2.1.3 拓展案例 1&#xff1a;Docker 中的 Flask 应用2.1.4 拓展案例 2&#xff1a;Docker 容器中的数据分析 2.2 创建与管理 Docker 镜像2.2.1 重点基础知识2.2.2 重点…