类和对象——对象的初始化和清理

 本文为观看 C++黑马程序员 的学习笔记。

构造函数和析构函数

构造函数:进行初始化操作

析构函数:进行清理操作

构造函数 语法:类名(){}

  1. 构造函数,没有返回值,也不写void
  2. 函数名称与类名相同
  3. 构造函数可以有参数,因此可以重载
  4. 程序在调用对象时,会自动调用构造,无需手动调用一次,而且只会调用一次

析构函数 语法:~类名(){}

  1. 析构函数,没有返回值,也不写void
  2. 函数名称与类名相同,在名称前加上符号~
  3. 析构函数不可以有参数,因此不可以发生重载
  4. 程序在对象销毁前会自动调用析构,无需手动调用,而且只会调用一次 

构造函数和析构函数语法: 

class Person
{
public://构造函数Person(){cout << "Person的构造函数调用" << endl;}//析构函数~Person(){cout << "Person的析构函数调用" << endl;}
};

函数的分类及调用

两种分类方式:

  • 按参数分为:有参构造和无参构造
  • 按类型分为:普通构造和拷贝构造

三种调用方式:

  • 括号法
  • 显示法
  • 隐式转换法

代码有问题,需要改正

拷贝构造函数调用时机

拷贝构造函数调用时机,有3中情况

  • 使用一个创建完毕的对象来初始化一个新对象
  • 值传递的方式给函数参数传值
  • 以值方式返回局部对象
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;//拷贝构造函数调用时机class Person 
{
public:Person(){cout << "Person默认构造函数调用" << endl;}Person(int age){cout << "Person有参构造函数调用" << endl;m_Age = age;}Person(const Person& p){ cout << "Person拷贝构造函数调用" << endl;m_Age = p.m_Age; }~Person(){cout << "Person析构函数调用" << endl;}int m_Age; //m_Age 一定要记得声明
};//1、使用一个创建完毕的对象来初始化一个新对象
void test01()
{Person p1(20);Person p2(p1);cout << "p2的年龄为: " << p2.m_Age << endl;
}//2、值传递的方式给函数参数传值void  doWork(Person p)
{}void test02()
{Person p;doWork(p);
}//3、以值方式返回局部对象Person doWork2()
{Person p1;cout << (int*)&p1 << endl;return p1;
}void test03()
{Person p = doWork2();cout << (int*)&p << endl;
}int main()
{//test01();test02();//test03();system("pause");
}

构造函数调用规则

默认情况下,c++编译器至少给一个类添加3个函数

1.默认构造函数(无参,函数体为空)

2.默认析构函数(无参,函数体为空)

3.默认拷贝构造函数,对属性进行值拷贝

构造函数 调用规则:

  • 如果用户定义有参构造函数,c++不在提供默认无参构造,但是会提供默认拷贝构造
  • 如果用户定义拷贝构造函数,c++不会再提供其他构造函数
#define _CRT_SECURE_NO_WARNINGS 1
using namespace std;
#include <iostream>//默认情况下,c++编译器至少给一个类添加3个函数//1.默认构造函数(无参,函数体为空)//2.默认析构函数(无参,函数体为空)//3.默认拷贝构造函数,对属性进行值拷贝//如果用户定义有参构造函数,c++不在提供默认无参构造,但是会提供默认拷贝构造
//如果用户定义拷贝构造函数,c++不会再提供其他构造函数class Person
{
public:/*Person(){cout << "Person的默认构造函数调用 " << endl;}*/Person(int age){cout << "Person的有参构造函数调用 " << endl;m_Age = age; }/*Person(const Person & p){cout << "Person的拷贝构造函数调用 " << endl;m_Age = p.m_Age;}*/~Person(){cout << "Person的析构函数调用 " << endl;}int m_Age;};//void test01()
//{
//	Person p;// 创建一个对象
//	p.m_Age = 18;
//
//	Person p2(p);
//
//	cout << "p2的年龄为: " << p2.m_Age << endl;
//}void test02()
{Person p(28);Person p2(p);cout << "p2的年龄为: " << p2.m_Age << endl;
}int main()
{//test01();test02();system("pause");
}

深拷贝与浅拷贝

深拷贝,面试经典考题

浅拷贝:简单的复制拷贝操作

深拷贝:在堆区重新申请空间,进行拷贝操作

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;//深拷贝与浅拷贝class Person {public:Person(){cout << "Person的默认构造函数调用" << endl;}Person(int age , int height){m_Age = age;m_Height = new int(height);cout << "Person的有参构造函数调用" << endl;}//自己实现拷贝构造函数,解决拷贝带来的问题Person(const Person& p){cout << "Person 拷贝构造函数调用" << endl;m_Age = p.m_Age;//m_Height = p.m_Height;编译器默认实现的就是这行代码,是浅拷贝//深拷贝操作m_Height = new int(*p.m_Height);//用深拷贝,在堆区重新创建一块空间,
//解决浅拷贝带来的堆区重复释放的问题}~Person(){// 析构代码,将堆区开辟数据做释放操作if (m_Height != NULL){delete m_Height;m_Height = NULL;}cout << "Person的析构函数调用" << endl;}int m_Age;//年龄int* m_Height;//身高
};void test01()
{Person p1(18,160);cout << "p1的年龄为: " << p1.m_Age << "  p1的身高为: " << *p1.m_Height << endl;Person p2(p1);cout << "p2的年龄为: " << p2.m_Age << "  p2的身高为: " << *p2.m_Height << endl;
}int main()
{test01(); 
}

总结:如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题

初始化列表

作用:初始化列表语法,用来初始化属性

语法:构造函数():属性1(值1),属性2(值2)...{ }

#define _CRT_SECURE_NO_WARNINGS 1
using namespace std;
#include <iostream>//初始化列表class Person
{
public://传统初始化方式//Person(int a, int b, int c)//{//	m_A = a;//	m_B = b;//	m_C = c;//}//初始化列表Person(int a, int b, int c) :m_A(a), m_B(b), m_C(c){}int m_A;int m_B;int m_C;};void test01()
{//Person p(10,20,30);Person p(10, 20, 30); // 创建对象cout << "m_A = " << p.m_A << endl;cout << "m_B = " << p.m_B << endl;cout << "m_B = " << p.m_B << endl;}int main()
{test01();system("pause");
}

类对象作为类成员

C++类中的成员可以是另一个类的对象,我们称该成员为 对象成员

例如:

class A{}
class B
{A  a;
}

上述,B类中有对象A作为成员,A为对象成员。

问:A和B的构造和析构顺序是谁先谁后? 

答:构造是先A后B,析构顺序相反。

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <string>
using namespace std;//类对象作为类成员// 手机类
class Phone
{public:Phone(string pName){cout << "Phone的构造函数调用" << endl;m_PName = pName;}~Phone(){cout << "Phone的析构函数调用" << endl;}//手机品牌名称string m_PName;
};// 人类
class Person  // Person为B
{
public:// Phone m_Phone = pName  隐式转换法Person(string name, string pName) : m_Name(name), m_Phone(pName){cout << "Person的构造函数调用" << endl;}~Person(){cout << "Person的析构函数调用" << endl;}// 姓名string m_Name;// 手机Phone m_Phone;  // Phone为A
};//void test01()
{Person p("张三" , "苹果MAX");cout << p.m_Name << "拿着:" << p.m_Phone.m_PName << endl;
}int main()
{test01();system("pause");
}

静态成员

静态成员,就是在成员变量和成员函数前加上关键字static,称为静态成员

静态成员分为:静态成员变量 、静态成员函数 

1、静态成员变量 特点:

  • 所有对象共享同一份数据
  • 在编译阶段分配内存
  • 类内声明,类外初始化

静态成员变量 不属于某个对象,所有对象都共享同一份数据

所以 静态成员变量有两种访问方式

  1. 通过对象进行访问
  2. 通过类名进行访问

静态成员变量也是有访问权限的

  1. 公有作用域类外可以访问
  2. 私有作用域类外不可以被访问
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;//静态成员变量
class Person
{
public://所有对象共享同一份数据//在编译阶段分配内存//类内声明,类外初始化static int m_A; // 类内声明 //静态成员变量也是有访问权限的
private:static int m_B;
};int Person::m_A = 100; // 类外初始化
int Person::m_B = 200;void test01()
{Person p;cout << p.m_A << endl;Person p2;p2.m_A = 200;  //100 ? 200cout << p.m_A << endl;  //所有对象共享同一份数据
}void test02()
{//静态成员变量 不属于某个对象,所有对象都共享同一份数据//所以 静态成员变量有两种访问方式//1.通过对象进行访问//Person p;             // 创建对象//cout << p.m_A << endl;//2.通过类名进行访问cout << Person::m_A << endl;cout << Person::m_B << endl;
}int main()
{//test01();test02();system("pause");return 0;
}

2、静态成员函数 特点:

  • 所有对象共享同一个函数
  • 静态成员函数只能访问静态成员变量
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;// 静态成员函数
//所有对象共享同一个函数
//静态成员函数只能访问静态成员变量class Person
{
public://静态成员函数static void func(){m_A = 100; // 静态成员函数可以访问 静态成员变量//m_B = 200; // 静态成员函数 不可以访问 非静态成员变量 ,无法区分到底是哪个对象的属性cout << "static void func调用 " << endl;}static int m_A; // 静态成员变量int m_B; // 非静态成员变量// 静态成员函数也是有访问权限的
private:static void func2(){cout << "static void func2调用" << endl;}
};// 有两种访问方式
void test01()
{//1、通过对象访问/*person p;p.func();*///2、通过类名访问Person::func();//Person::func2(); // 类外访问不到私有静态成员函数
}int main()
{test01();
}

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

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

相关文章

Python 实验五 高级数据结构

一、实验目的 &#xff08;1&#xff09;掌握序列的基本操作 &#xff08;2&#xff09;掌握集合、字典的基本操作 二、实验环境 联网计算机一台/每人&#xff0c;内装Windows 7以上操作系统和安装Python 3.7集成开发环境IDLE。 三、实验内容 Sy5-1 列表实现。编写一个…

CentOS 7 网络配置

如想了解请查看 虚拟机安装CentOS7 第一步&#xff1a;查看虚拟机网络编辑器、查看NAT设置 &#xff08;子网ID&#xff0c;网关IP&#xff09; 第二步&#xff1a;配置VMnet8 IP与DNS 注意事项&#xff1a;子网掩码与默认网关与 第一步 保持一致 第三步&#xff1a;网络配置…

解决一下git clone失败的问题

1&#xff09;.不开梯子&#xff0c;我们用https克隆 git clone https://github.com 报错&#xff1a; Failed to connect to github.com port 443 after 2091 ms: Couldnt connect to server 解决办法&#xff1a; 开梯子&#xff0c;然后# 注意修改成自己的IP和端口号 gi…

中伟视界:矿山智能化——未戴自救器检测AI算法实时检测井下作业人员自救器佩戴情况

矿山作业环境复杂且危险&#xff0c;确保作业人员佩戴必要的安全设备是保障安全生产的重要措施之一。自救器是井下作业人员必须佩戴的重要防护设备&#xff0c;用于在突发危险时保护生命安全。未戴自救器检测AI算法通过先进的图像识别和人工智能技术&#xff0c;实时监控井下人…

STM32第二十一课:FreeRTOS事件组软件定时器

目录 一、事件组1.事件组创建2.事件组置位3.事件组等待 二、软件定时器1.软件定时器创建2.软件定时器执行3.例程代码 一、事件组 本质上是任务同步&#xff0c;但比二值信号量优秀的是可以一对多。 我的理解&#xff1a;事件组就是标志位的集合&#xff0c;将多个标志位放到一个…

昇思25天学习打卡营第23天|DCGAN生成漫画头像

今天是参加昇思25天学习打卡营的第23天&#xff0c;今天打卡的课程是“DCGAN生成漫画头像”&#xff0c;这里做一个简单的分享。 1.简介 DCGAN&#xff08;深度卷积对抗生成网络&#xff0c;Deep Convolutional Generative Adversarial Networks&#xff09;是GAN的直接扩展。…

ArkUI状态管理

State装饰器 在声明式UI中&#xff0c;是以状态驱动试图更新 状态 (State) 指驱动视图更新的数据(被装饰器标记的变量) 试图(View) 基于UI描述渲染得到用户界面 说明 1.State装饰器标记的变量必须初始化&#xff0c;不能为空 2.State支持Object、classstring、number、b…

kettle从入门到精通 第七十六课 ETL之kettle kettle连接hive教程

1、群里有小伙伴询问kettle连接hive的demo&#xff0c;今天抽点时间整理下。其实kettle连接hive和连接mysql数据库也是一样的。 1&#xff09;kettle中的lib目录下放hive驱动jar&#xff0c;这里我使用的是kyuubi-hive-jdbc-shaded-1.9.0.jar。 2&#xff09;设置hive连接参数…

Ubuntu部署K8S集群-图文并茂(超详细)

Ubuntu部署K8S集群 1. 模版机系统环境准备1.1 安装Ubuntu1.2 设置静态IP地址 2. 主机准备2.1 使用模板机创建主机2.2 主机配置2.2.1 修改静态IP2.2.2 修改主机名2.2.3 主机名-IP地址解析2.2.4 时间同步2.2.5 内核转发、网桥过滤配置2.2.6 安装ipset和ipvsadm2.2.7 关闭SWAP分区…

pnpm install安装失败

ERR_PNPM_META_FETCH_FAIL GET https://registry.npmjs.org/commitlint%2Fcli: request to https://registry.npmjs.org/commitlint%2Fcli failed, reason: connect ETIMEDOUT 2606:4700::6810:123:443 1. 检查网络连接 确保你的网络连接正常并且没有被防火墙或代理服务器阻止…

【docker 部署springboot项目】

一、docker安装 1.检查Linux内核版本高于3.10才可安装 uname -r 2. 卸载旧版本 sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine 3. 使用docker仓库进行安装 安装所需的软…

java代理模式之JDK动态代理

目录 什么是动态代理&#xff1f; 动态代理的两种方式&#xff1f; jdk动态代理&#xff1b; cglib静态代理 为什么需要代理&#xff1f; 1、原有功能增强 2、降低耦合 JDK动态代理代码实例&#xff1a; 实体类&#xff1a; 持久层接口实现类&#xff08;使用jdbc进行…

【2024】VsCode + Latex + Linux(Ubuntu) + wsl环境下配置教程 | 包含 中文配置,和 格式化处理

前言 本篇教程是针对WSL下的Ubuntu操作系统的配置教程&#xff0c;它和一般的Linux环境下的配置有所不同&#xff0c;并且和Windows环境下的也有所不同。 本篇博客编写参考了 官方文档&#xff08;Tex&#xff09; 和 插件官方&#xff08;Texlive Workshop&#xff09; 文档…

动手学RAG:Part1 什么是RAG?

1、大模型的幻觉问题、时效性问题、数据安全问题 2、大模型的结构和参数数量导致对其修改、微调和重新训练变得很困难 3、基于知识的问答&#xff0c;依赖于信息抽取

Logback日志异步打印接入指南,输出自定义业务数据

背景 随着应用的请求量上升&#xff0c;日志输出量也会成线性比例的上升&#xff0c;给磁盘IO带来压力与性能瓶颈。应用也遇到了线程池满&#xff0c;是因为大量线程卡在输出日志。为了缓解日志同步打印&#xff0c;会采取异步打印日志。这样会引起日志中的追踪id丢失&#xf…

2024 HNCTF PWN(close ezpwn idea what beauty)

文章目录 closeezpwn代码利用exp idea代码exp whatexp beauty libc 2.35IDA中文乱码解决代码思路exp close int __fastcall main(int argc, const char **argv, const char **envp) {puts("**********************************");puts("* Welcome to the H…

kubernetes k8s Deployment 控制器配置管理 k8s 红蓝部署 金丝雀发布

目录 1、Deployment控制器&#xff1a;概念、原理解读 1.1 Deployment概述 1.2 Deployment工作原理&#xff1a;如何管理rs和Pod&#xff1f; 2、Deployment资源清单文件编写技巧 3、Deployment使用案例&#xff1a;创建一个web站点 4、Deployment管理pod&#xff1a;扩…

数字化装备场革新:智能装备采集设备问世!

数字化装备场建设是一项跨学科的综合工程&#xff0c;它不仅涵盖了网络布线的整合、系统框架的构建&#xff0c;还包含了各类硬件设备的配置等丰富多样的内容。该工程的关键环节主要包括对装备场所的出入口进行现代化升级、完善车库车辆定位与管理体系&#xff0c;以及部署一体…

Maven学习——Maven的下载、安装与配置(详细攻略!)

目录 前言 1.下载与安装 2.配置Maven的环境变量 3.配置Maven的本地仓库 4. 配置Maven的镜像远程仓库 前言 我在之前写了一篇博客&#xff0c;是介绍Maven的基本概念和下载安装&#xff0c;但是由于篇幅过长&#xff0c;Maven的下载与安装写的并不详细&#x1f436;&#x…

kaggle 量化交易 比赛

作者: Raoul Malm 描述: 本笔记本演示了如何使用 TensorFlow 中的循环神经网络预测不同股票的未来价格。实现了带有基本单元、LSTM 或 GRU 单元的循环神经网络。 大纲: [库和设置][分析数据][操作数据][建模和验证数据][预测]参考: https://www.kaggle.com/benjibb/lstm-st…