【C++】类和对象-对象特性

news2024/9/22 4:17:15

1.构造函数和析构函数

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

2.函数的分类以及调用

以后采用括号法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

int main()
{
/******************************************/
	//test01();
	//test02();
	Person p;


/******************************************/
	system("pause");

	return 0;
}

(1)以后采用括号法

	Person p1;		//默认构造函数调用
	Person p2(10);  //有参构造函数
	Person p3(p1);  //拷贝构造函数

在这里插入图片描述

3.拷贝构造函数调用时机

在这里插入图片描述

#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;
};

//1、使用一个已经创建完毕的对象来初始化一个新对象
void test01() {
	Person p1(10);
	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 p2 = doWork2();
	cout <<  (int*) & p2 << endl;
}

/******************************************/
int main()
{
/******************************************/
	test01();
	test02();
	test03();

/******************************************/
	system("pause");

	return 0;
}

4.构造函数调用规则

在这里插入图片描述

#include <iostream>
using namespace std;
/******************************************/

//构造函数的调用规则
//1、创建一个类,C++编译器会给每个类都添加至少三个函数:
//默认构造  (空实现)
//析构函数  (空实现)
//拷贝构造  (值拷贝)

//2、
//如果我们写了有参构造函数,编译器就不再提供默认构造,依然提供拷贝构造
//如果我们写了拷贝构造函数,编译器就不再提供其他普通构造函数了
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(10);
	Person p2(p);

	cout << "p2的值:" << p2.m_Age << endl;
}
/******************************************/
int main()
{
/******************************************/
	//test01();
	test02();


/******************************************/
	system("pause");

	return 0;
}

5.深拷贝与浅拷贝

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

#include <iostream>
using namespace std;
/******************************************/

//深拷贝与浅拷贝

class Person {
public:
	Person() {
		cout << "Person默认构造函数调用" << endl;
	}
	Person(int age, int height) {
		cout << "Person有参构造函数调用" << endl;
		m_Age = age;
		m_Height = new int(height);//在堆区开辟数据,并返回的是地址
	}
	Person(const Person& p) {
		cout << "Person拷贝构造函数调用" << endl;
		m_Age = p.m_Age;
	}

	~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, 180);
	cout << "p1的年龄为:" << p1.m_Age << "p1的身高为:" << *p1.m_Height << endl;

	Person p2(p1);
	cout << "p1的年龄为:" << p2.m_Age << "p2的身高为:" << *p2.m_Height << endl;
}

/******************************************/
int main()
{
/******************************************/
	test01();
/******************************************/
	system("pause");

	return 0;
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
解决方式:

	//自己实现拷贝构造函数 解决浅拷贝带来的问题
	Person(const Person& p) {
		cout << "Person拷贝构造函数调用" << endl;
		m_Age = p.m_Age;
		//m_Height = p.m_Height;//编译器默认实现的就是这行代码

		//深拷贝操作
		m_Height = new int(*p.m_Height);
	}

总代码:

#include <iostream>
using namespace std;
/******************************************/

//深拷贝与浅拷贝

class Person {
public:
	Person() {
		cout << "Person默认构造函数调用" << endl;
	}
	Person(int age, int height) {
		cout << "Person有参构造函数调用" << endl;
		m_Age = age;
		m_Height = new int(height);//在堆区开辟数据,并返回的是地址
	}

	//自己实现拷贝构造函数 解决浅拷贝带来的问题
	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, 180);
	cout << "p1的年龄为:" << p1.m_Age << "p1的身高为:" << *p1.m_Height << endl;

	Person p2(p1);
	cout << "p1的年龄为:" << p2.m_Age << "p2的身高为:" << *p2.m_Height << endl;
}

/******************************************/
int main()
{
/******************************************/
	test01();


/******************************************/
	system("pause");

	return 0;
}

6.初始化列表

在这里插入图片描述
代码:

#include <iostream>
using namespace std;
/******************************************/

//初始化列表
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(c), m_C(b) {

	}

	int m_A;
	int m_B;
	int m_C;
};

void test01() {
	Person p(10,20,30);
	cout << p.m_A << p.m_B << p.m_C << endl;
}

/******************************************/
int main()
{
	/******************************************/
	test01();


	/******************************************/
	system("pause");

	return 0;
}

输出结果:
在这里插入图片描述

7.类对象作为类成员

在这里插入图片描述
当其他类对象作为本类成员,构造时候先构造类对象,再构造自身,析构的顺序与构造相反

代码:

#include <iostream>
using namespace std;
/******************************************/

class Phone {
public:
	Phone(string Pname) {
		cout << "Phone的构造函数调用" << endl;
		m_Pname = Pname;
	}

	~Phone() {
		cout << "Phone的析构函数调用" << endl;
	}

	string m_Pname;//手机品牌
};

//人类
class Person {
public:
	//m_Phone(pName)相当于Phone m_Phone = pName 隐性转换法  或  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;//手机
};
//当其他类对象作为本类成员,构造时候先构造类对象,再构造自身,析构的顺序与构造相反

void test01() {
	Person p("小王", "小米K30");

	cout << endl << p.m_Name<< "  拥有:  " << p.m_Phone.m_Pname << endl << endl;
}

/******************************************/
int main()
{
	/******************************************/
	test01();


	/******************************************/
	system("pause");

	return 0;
}

8.静态成员

在这里插入图片描述

(1)静态成员变量

代码:

#include <iostream>
using namespace std;
/******************************************/

//静态成员变量
class Person {
public:
	//1 所有对象都共享同一份数据
	//2 编译阶段就分配内存
	//3 类内声明,类外初始化操作
	static int m_A;

	//静态成员变量也有访问权限
private:
	static int m_B;
};

int Person::m_A = 100;//类外初始化操作
int Person::m_B = 200;//类外初始化操作

void test01() {
	Person p;
	//100
	cout << p.m_A << endl;

	Person p2;
	p2.m_A = 200;
	//200
	cout << 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;//类外访问不到私有静态成员变量(见于14、15行代码)
}
/******************************************/
int main()
{
	/******************************************/
	//test01();
	test02();


	/******************************************/
	system("pause");

	return 0;
}

(2)静态成员函数

代码:

#include <iostream>
using namespace std;
/******************************************/

//静态成员函数
//1、所有对象共享同一份函数
//2、静态成员函数只能访问静态成员变量

class Person {
public:
	//静态成员函数
	static void func() {
		m_A = 100;//静态成员函数可以访问 静态成员变量
		//m_B = 200;//静态成员函数不可以访问 非静态成员变量,无法区分到底是哪个对象的m_B属性
		cout << "static void func()调用" << endl;
	}

	static int m_A;//静态成员变量
	int m_B;  //  非静态成员变量

	//静态成员函数也有访问权限
private:
	static void func2() {
		cout << "static void func2()调用" << endl;
	}
};

int Person::m_A = 0;

//有两种访问方式
void test01() {
	//1、通过对象访问
	Person p;
	p.func();

	//2、通过类名访问
	Person::func();

	//Person::func2();  类外访问不到私有静态成员函数
}

/******************************************/
int main()
{
	/******************************************/
	test01();


	/******************************************/
	system("pause");

	return 0;
}

9.成员变量和成员函数分开存储

在这里插入图片描述

#include <iostream>
using namespace std;
/******************************************/

//成员变量 和 成员函数 分开存储的

class Person {
//public:
	int m_A;  //非静态成员变量 属于类的对象上

	static int m_B; //静态成员变量 不属于类的对象上

	void func(){} //非静态成员函数 不属于类的对象上

	static void func2(){} //静态成员函数 不属于类的对象上
};

int Person::m_B = 0;

void test01() {
	Person p;
	//空对象占用内存空间为:1
	//C++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置
	//每个空对象也应该有一个独一无二的内存地址
	cout << "size of p :" << sizeof(p) << endl;
}

void test02() {
	Person p;
	
	cout << "size of p :" << sizeof(p) << endl;
}
/******************************************/
int main()
{
	/******************************************/
	test01();
	test02();

	/******************************************/
	system("pause");

	return 0;
}

10.this指针的用途

在这里插入图片描述

#include <iostream>
using namespace std;
/******************************************/

//1、解决名称冲突

//2、返回对象本身用*this

class Person {
public:
	Person(int age) {
		//this指针指向 被调用的成员函数所属的对象
		this->age = age;
	}

	Person& PersonAddAge(Person& p) {
		this->age += p.age;

		//this指向p2的指针,而*this指向的就是p2这个对象本体
		return *this;
	}

	int age;//可以直接把age改成m_Age,就不用this了
};

//1、解决名称冲突
void test01() {
	Person p(12);
	
	cout << p.age << endl;
}

//2、返回对象本身用*this
void test02() {
	Person p1(10);
	Person p2(10);

	//链式编程思想
	p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);

	cout << p2.age << endl;
}

/******************************************/
int main()
{
	/******************************************/
	test01();
	test02();

	/******************************************/
	system("pause");

	return 0;
}

结果
在这里插入图片描述
如果16-21行代码改成如下:

	Person PersonAddAge(Person& p) {
		this->age += p.age;

		//this指向p2的指针,而*this指向的就是p2这个对象本体
		return *this;
	}

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

Person PersonAddAge(Person& p){
}

它是拷贝构造函数

11.空指针访问成员函数

在这里插入图片描述

#include <iostream>
using namespace std;
/******************************************/

//空指针调用成员函数

class Person
{
public:
	void showClassName()
	{
		cout << "this is Person class" << endl;
	}

	void showPersonAge() {
		//报错原因是因为传入的指针是为NULL
		if (this == NULL) {
			return;
		}

		cout << "age = " << m_Age << endl;//相当于cout << "age = " << this->m_Age << endl;
	}

	int m_Age;
};

void test01() {
	Person* p = NULL;

	p->showClassName();

	p->showPersonAge();
}
/******************************************/
int main()
{
	/******************************************/
	test01();

	/******************************************/
	system("pause");

	return 0;
}

12.const修饰成员函数

在这里插入图片描述

#include <iostream>
using namespace std;
/******************************************/

//常函数
class Person {
public:
	//this指针的本质 是指针常量 指针的指向是不可以修改的
	//const Person* const this;
	//在成员函数后面加const,修饰的是this指向,让指针指向的值也不可以修改
	void showPerson() const{
		this->m_B = 100;
		//this->m_A = 100;
		//this = NULL;//this指针不可以修改指针的指向的
	}

	void func() {
		m_A = 100;
	}

	int m_A;
	mutable int m_B;//特殊变量,即使在常函数中,也可以修改这个值,加关键字mutable
};

void test01() {
	Person p;
	p.showPerson();

	cout << p.m_B;
}

void test02() {
	const Person p;//在对象前加const,变为常对象
	//p.m_A = 100;//左值不能修改
	p.m_B = 100;//m_B是特殊值,在常对象下也可以修改

	//常对象只能调用常函数
	p.showPerson();
	//p.func();//常对象 不可以调用普通成员函数,因为普通成员函数可以修改属性
}
/******************************************/
int main()
{
	/******************************************/
	test01();

	/******************************************/
	system("pause");

	return 0;
}

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

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

相关文章

行业追踪,2023-07-27

自动复盘 2023-07-27 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…

linux系统下(centos7.9)安装Jenkins全流程

一、卸载历史版本 # rpm卸载 rpm -e jenkins# 检查是否卸载成功 rpm -ql jenkins# 彻底删除残留文件 find / -iname jenkins | xargs -n 1000 rm -rf二、环境依赖安装 yum -y install epel-releaseyum -y install daemonize三、安装Jenkins Jenkins官网传送带&#xff1a; …

【bar堆叠图形绘制】

绘制条形图示例 在数据可视化中&#xff0c;条形图是一种常用的图表类型&#xff0c;用于比较不同类别的数据值。Python的matplotlib库为我们提供了方便易用的功能来绘制条形图。 1. 基本条形图 首先&#xff0c;我们展示如何绘制基本的条形图。假设我们有一个包含十个类别的…

【数据结构】实验四:循环链表

实验四 循环链表 一、实验目的与要求 1&#xff09;熟悉循环链表的类型定义和基本操作&#xff1b; 2&#xff09;灵活应用循环链表解决具体应用问题。 二、实验内容 题目一&#xff1a;有n个小孩围成一圈&#xff0c;给他们从1开始依次编号&#xff0c;从编号为1的小孩开…

写给新手的单元测试框架unittest运行的简单问题

当使用unittest框架编写和运行单元测试时&#xff0c;需要遵循以下步骤&#xff1a; 1、导入unittest模块&#xff1a;在代码中首先导入unittest模块。 import unittest 2、创建测试类&#xff1a;创建一个继承自unittest.TestCase的测试类。该类将包含一系列测试方法。 cla…

#P1006. [NOIP2010普及组] 三国游戏

题目描述 小涵很喜欢电脑游戏&#xff0c;这些天他正在玩一个叫做《三国》的游戏。 在游戏中&#xff0c;小涵和计算机各执一方&#xff0c;组建各自的军队进行对战。游戏中共有 NN 位武将&#xff08;NN为偶数且不小于44&#xff09;&#xff0c;任意两个武将之间有一个“默…

什么是低代码开发平台?它可以实现哪些功能?

什么是低代码开发平台&#xff1f; 低代码来源于英文“Low Code&#xff0c;它意指一种快速开发的方式&#xff0c;使用最少的代码、以最快的速度来交付应用程序。通俗的来说&#xff0c;就是所需代码数量低&#xff0c;开发人员门槛低&#xff0c;操作难度低。一般采用简单的…

模拟实现二叉搜索树

1、TreeSet和TreeMap插入元素时一定要比较大小&#xff0c;因为其底层是红黑树&#xff08;由二叉搜索树调整形成&#xff09;。 2、删除二叉搜索树的目标节点时有三种情况&#xff1a; &#xff08;1&#xff09;cur.leftnull ①cur是root&#xff0c;则rootcur.right ②cur不…

一百多行 C 语言代码实现一个简单异步事件触发机制!

一、简介 QT 中有一种异步处理机制叫做信号和槽函数&#xff0c;通过将信号与槽函数进行绑定连接&#xff0c;后续若该信号触发&#xff0c;会自动调用对应的槽函数。这种机制很适合处理很繁琐的逻辑程序&#xff0c;例如我点击界面的 close 按钮&#xff0c;便触发 close 信号…

基于穷举搜索的AI自动实现俄罗斯方块游戏(核心代码详解)

一、算法思想核心 这个俄罗斯方块AI的核心思想是通过穷举搜索当前形状和下一个形状的所有可能的放置组合&#xff0c;并为每个组合计算一个得分。得分是根据游戏板面的状态来评估每个组合的优劣&#xff0c;最终选择得分最高的放置策略。 具体的实现步骤和核心思想如下&#…

怎么恢复回收站清空的文件,教你三种恢复的方法

不论是笔记本电脑还是台式机电脑&#xff0c;都有回收站这样的“后悔药”&#xff0c;我们许多误删除的文件夹、图片、视频、文档等都能从它里面找到&#xff0c;回收站在灵活运用下能更好地为我们服务&#xff0c;但是使用过程中难免会出现失误&#xff0c;比如说不小心清空了…

pdf合并大小不一样怎么办?有这几个方法就够了

pdf合并大小不一样怎么办&#xff1f;在日常工作和生活中&#xff0c;我们经常需要处理PDF文件。在将多个PDF文件合并成一个时&#xff0c;由于这些文件的大小和格式可能不同&#xff0c;可能会遇到一些问题。但不用担心&#xff0c;接下来将介绍几种方法来解决这个问题。 方法…

JAVA缓存技术介绍

OSCache OSCache是个一个广泛采用的高性能的J2EE缓存框架&#xff0c;OSCache能用于任何Java应用程序的普通的缓存解决方案。 OSCache有以下特点&#xff1a; 我创建了一个群&#xff0c;群里不定期分享技术干货&#xff0c;行业秘闻&#xff0c;汇集各类奇妙好玩的话题和流行动…

Individual household electric power consumption个人家庭用电量数据挖掘与时序预测建模

今天接到一个任务就是需要基于给定的数据集来进行数据挖掘分析相关的计算&#xff0c;并完成对未来时段内数据的预测建模&#xff0c;话不多少直接看内容。 官方数据详情介绍在这里&#xff0c;如下所示&#xff1a; 数据集中一共包含9个不同的字段&#xff0c;详情如下&#…

MinIO对象存储

MinIO 是一个高性能的分布式对象存储系统。 它是软件定义的&#xff0c;在行业标准硬件上运行&#xff0c;并且 100% 开源&#xff0c;主要许可证是 GNU AGPL v3。 MinIO 的不同之处在于它从一开始就被设计为私有/混合云对象存储的标准。 因为 MinIO 是专门为对象而构建的&…

day14 | 100.二叉树的最大深度 111.二叉树的最小深度 222.完全二叉树的节点个数

文章目录 一、二叉树的最大深度二、二叉树的最小深度三、完全二叉树的节点数 一、二叉树的最大深度 100.二叉树的最大深度 因为题给出的高度和深度是一样的&#xff0c;所以求得结果都能过。 class Solution { public:int getHeight(TreeNode *node){if (node nullptr)retu…

Qt 第三讲 手动拖动ui界面组件,事件处理机制,实现简单闹钟

手动拖动ui界面组件&#xff0c;实现闹钟 源文件 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);ui->btn_end->setEnabled(false);speecher new QTex…

Linux基础内容(29)—— 额外锁

Linux基础内容&#xff08;28&#xff09;—— POSIX信号量与循环队列_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/131844590?spm1001.2014.3001.5501 目录 1.其他常见的各种锁 自旋锁 库语言的实现 2.读者写者问题 1.读者写者线程 2.…

SpringMVC启动时非常缓慢,显示一直在部署中,网页也无法访问,,,Artifact is being deployed, please wait...

写了一个基本的SpringMVC程序进行测试&#xff0c;结果启动时一直显示在等待部署完毕&#xff0c;&#xff0c;&#xff0c; but这个地方一直显示转圈圈。。 后来通过url访问时网页一直转圈圈。。也就是等待响应。。 看了一会儿&#xff0c;也不知道哪儿错了&#xff0c;&…

什么是多运行时架构?

服务化演进中的问题 自从数年前微服务的概念被提出&#xff0c;到现在基本成了技术架构的标配。微服务的场景下衍生出了对分布式能力的大量需求&#xff1a;各服务之间需要相互协作和通信&#xff0c;以及共享状态等等&#xff0c;因此就有了各种中间件来为业务服务提供这种分…