【第三天】C++类和对象进阶指南:从堆区空间操作到友元的深度掌握

一、new和delete 堆区空间操作

1、new和delete操作基本类型的空间

new与C语言中mallocdelete和C语言中free 作用基本相同

 区别:

new 不用强制类型转换

new在申请空间的时候可以 初始化空间内容

2、 new申请基本类型的数组

 3、new和delete操作类的空间

 4、new申请操作对象数组

 二、静态成员

1、概念

类的对象 拥有独立的 普通成员数据。

static 修饰的成员 叫 静态成员。

class Data
{int a;//普通成员数据static int a;//静态成员数据static void func()//静态成员函数
{
}
};

2、静态成员数据

static修饰的静态成员 属于类而不是对象(所有对象 共享 一份 静态成员数据)。

实战案例:使用静态成员数据 统计对象的个数

#pragma warning(disable:4996)
#include<iostream>
using namespace std;
class Data
{
public:int mA;//普通成员数据static int count;//静态成员数据
public:Data(){count++;}Data(int a){mA = a;count++;}Data(const Data &ob){count++;}~Data(){count--;}
};
//类外初始化
int Data::count = 0;
void test()
{Data ob1;Data ob2(10);Data ob3 = ob2;cout << "对象个数:" << Data::count << endl;//3{Data ob4;Data ob5;cout << "对象个数:" << Data::count << endl;//5}cout << "对象个数:" << Data::count << endl;//3
}
int main(int argc, char* argv[])
{test();return 0;}

 3、静态成员函数

静态成员函数直接通过类名称访问

静态成员函数内 只能操作静态成员数据,因为普通成员数据还没有空间。

 三、单例模式

        单例模式可以保证结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。即单例模式的类 只能实例化 一个对象。

        核心:将构造函数私有化

#include <iostream>
using namespace std;
class SingleTon//单例模式
{
//构造私有化 防止实例化其他对象
private:SingleTon(){count=0;cout<<"构造"<<endl;}SingleTon(const SingleTon &ob){count=0;}~SingleTon(){cout<<"析够"<<endl;}
private://const防止p 在类内部 被修改指向static SingleTon * const p;//保存唯一的实例地址int count;//统计任务执行次数public:static SingleTon * getSingleTon(void)//获取唯一的实例地址{return p;}//用户自定义 任务函数void printString(char *str){count++;cout<<"当前第"<<count<<"次任务打印:"<<str<<endl;}
};
SingleTon *const SingleTon::p = new SingleTon;//创建唯一的实例int main(int argc, char *argv[])
{//获取单例的地址SingleTon *p1 =SingleTon::getSingleTon();//执行任务p1‐>printString("学历证明1");p1‐>printString("身份证明1");SingleTon *p2 =SingleTon::getSingleTon();p2‐>printString("学历证明2");p2‐>printString("身份证明2");
}

四、类的存储结构

        成员函数静态成员 是独立存储 是所有对象共享,不占类的空间。

五、this指针

         this是一个隐藏的指针,可以在类的成员函数中使用,它可以用来指向调用对象。当一个对象的成员函数被调用时,编译器会隐式地传递该对象的地址作为 this 指针。

        this 指针是一个特殊的指针,它指向当前对象的实例。每一个对象都能通过 this 指针来访问自己的地址。

        this可以完成链式操作 

六、const修饰成员函数 

        const 修饰成员函数为只读(该成员函数不允许对 成员数据 赋值mutable修饰的成员除外

七、友元

        预知识:将数据和方法封装在一起 加以权限区分 用户只能通过公共方法 操作私有数据。(封装 性)

        定义:一个函数或者类 作为了另一个类的友元 那么这个函数或类 就可以直接访问 另一个类的私 有数据。应用:友元 主要用在运算符重载上

        友元语法:friend关键字只出现在声明处,其他类、类成员函数、全局函数都可声明为友元,友元函数不是类的成员,不带 this指针友元函数可访问对象任意成员属性,包括私有属性。

        现实生活中也可以很好地理解:比如你的家,有客厅,有你的卧室,那么你的客厅是Public的,所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去,但是呢,你也可以允许你的闺蜜好基友进去。程序员可以把一个全局函数、某个类中的成员函数、甚至整个类声明为友元

1、普通全局函数 作为类的友元

2、 类的某个成员函数 作为另一个类的友元

#pragma warning(disable:4996)
#include<iostream>
#include <string>
using namespace std;
class room;//向前声明,只能说明类名称
class Frind
{
public:void visiting01(Room& room);void visiting02(Room& room);
};
class Room
{friend void goodGay::visiting02(Room &room);
private:string bedroom;//实例化对象
public:string livingroom;
public:Room(string bedroom,string livingroom){this-> bedroom = bedroom;this-> livingroom = livingroom;}
};
void test()
{Room room("我的卧室", "我的客厅");Frind ob;ob.visiting01(room);ob.visiting02(room);
}
int main(int argc, char* argv[])
{test();return 0;}void Frind::visiting01(Room& room)
{cout << "李四访问到" << room.livingroom << endl;//cout<<"李四访问到"<<room.bedRoom<<endl;该成员函数不是类的友元,报错
}void Frind::visiting02(Room& room)
{cout << "好基友张三访问到" << room.livingroom << endl;cout << "好基友张三访问到" << room.bedroom << endl;}

 3、整个类作为 另一个类的友元

         这个类的所有成员函数 都可以访问另一个类的私有数据

#pragma warning(disable:4996)
#include<iostream>
#include <string>
using namespace std;
class room;//向前声明,只能说明类名称
class Frind
{
public:void visiting01(Room& room);void visiting02(Room& room);
};
class Room
{friend class Frind;
private:string bedroom;//实例化对象
public:string livingroom;
public:Room(string bedroom,string livingroom){this-> bedroom = bedroom;this-> livingroom = livingroom;}
};
void test()
{Room room("我的卧室", "我的客厅");Frind ob;ob.visiting01(room);ob.visiting02(room);
}
int main(int argc, char* argv[])
{test();return 0;}void Frind::visiting01(Room& room)
{cout << "李四访问到" << room.livingroom << endl;cout<<"李四访问到"<<room.bedRoom<<endl;
}void Frind::visiting02(Room& room)
{cout << "好基友张三访问到" << room.livingroom << endl;cout << "好基友张三访问到" << room.bedroom << endl;}

4、案例

(1)遥控器的类

#include <iostream>
using namespace std;
class TV;
class Remote//遥控器类
{
private:TV *p;
public:Remote(TV *p);void offOrOn(void);//开关void upVolume(void);//音量void downVolume(void);void upChannel(void);//频道void downChannel(void);void showTv(void);void setChannel(int channel);
};
class TV
{friend void Remote::setChannel(int channel);enum{OFF, ON};enum{minVol, maxVol=10};enum{minChan, maxChan=25};
private:int state;int volume;int channel;
public:TV(){state = OFF;volume = minVol;channel = minChan;}void offOrOn(void);void upVolume(void);void downVolume(void);void upChannel(void);void downChannel(void);void showTv(void);};
int main(int argc, char *argv[])
{//实例化一个电视机TV tv;Remote re(&tv);re.offOrOn();re.upVolume();re.upVolume();re.upVolume();re.setChannel(20);re.showTv();return 0;
}
void TV::offOrOn()
{state = (state==OFF?ON:OFF);return;
}
void TV::upVolume()
{if(volume == maxVol){cout<<"音量已经最大了"<<endl;return;
}volume++;return;
}void TV::downVolume()
{if(volume == minVol){cout<<"音量已经最小了"<<endl;return;
}volume‐‐;return;
}
void TV::upChannel()
{if(channel == maxChan){cout<<"频道已经最大了"<<endl;return;}channel++;return;
}void TV::downChannel()
{if(channel == minChan){cout<<"频道已经最小了"<<endl;return;}channel‐‐;return;
}
void TV::showTv()
{cout<<"当前电视机的状态:"<<(state==OFF?"关":"开")<<endl;cout<<"当前电视机的音量:"<<volume<<endl;cout<<"当前电视机的频道:"<<channel<<endl;
}
Remote::Remote(TV *p)
{this‐>p = p;
}
void Remote::offOrOn()
{p‐>offOrOn();
}void Remote::upVolume()
{p‐>upVolume();
}
void Remote::downVolume()
{p‐>downVolume();
}void Remote::upChannel()
{p‐>upChannel();
}void Remote::downChannel()
{p‐>downChannel();
}void Remote::showTv()
{p‐>showTv();
}
void Remote::setChannel(int channel)
{p‐>channel = channel;
}

(2)动态数组类

        根据数据大小动态增减空间。

array.h

#ifndef ARRAY_H
#define ARRAY_H
class Array
{
private:int *arr;//存放首元素地址int capacity;//容量int size;//大小
public:Array();Array(int capacity);Array(const Array &ob);~Array();int getCapacity() const;int getSize() const;void printArray(void);//插入尾部元素void pushBack(int elem);//删除尾部元素void popBack(void);int &at(int pos);
};#endif // ARRAY_H

array.cpp

#include "array.h"
#include<string.h>
#include<iostream>
using namespace std;
int Array::getCapacity() const
{return capacity;
}int Array::getSize() const
{return size;
}void Array::printArray()
{int i=0;for(i=0;i<size; i++){cout<<arr[i]<<" ";}cout<<endl;return;
}void Array::pushBack(int elem)
{//判断容器是否满if(size == capacity){//申请空间int *tmp = new int[2*capacity];//将就空间的内容 拷贝到新空间memcpy(tmp, arr, capacity*sizeof(int));//释放原有的空间delete [] arr;//更新arr的空间arr = tmp;//更新容量capacity = 2*capacity;}arr[size]=elem;size++;return;
}
void Array::popBack()
{if(size == 0){cout<<"容量为空"<<endl;}    else{size‐‐;}return;
}
int& Array::at(int pos)
{if(pos<0 || pos >=size){cout<<"访问违法内存"<<endl;exit(‐1);}return arr[pos];
}
Array::Array()
{capacity = 5;size = 0;arr = new int[capacity];//空间清0memset(arr, 0, sizeof(int)*capacity);
}
Array::Array(int capacity)
{this‐>capacity = capacity;size = 0;arr = new int[capacity];//空间清0memset(arr, 0, sizeof(int)*capacity);
}
Array::Array(const Array &ob)
{capacity = ob.capacity;size = ob.size;//深拷贝arr = new int[capacity];memcpy(arr, ob.arr, sizeof(int)*capacity);
}
Array::~Array()
{if(arr != NULL){delete [] arr;arr = NULL;}
}

main.c

#include <iostream>
#include "array.h"
using namespace std;
int main(int argc, char *argv[])
{Array ob;cout<<ob.getCapacity()<<" "<<ob.getSize()<<endl;ob.pushBack(10);ob.pushBack(20);ob.pushBack(30);ob.pushBack(40);ob.printArray();cout<<ob.getCapacity()<<" "<<ob.getSize()<<endl;ob.pushBack(50);ob.pushBack(60);ob.printArray();cout<<ob.getCapacity()<<" "<<ob.getSize()<<endl;ob.popBack();ob.popBack();ob.printArray();cout<<ob.getCapacity()<<" "<<ob.getSize()<<endl;cout<<"arr[2] = "<<ob.at(2)<<endl;ob.at(2) = 100;ob.printArray();return 0;
}

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

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

相关文章

数据可视化在行业解决方案中的实践应用 ——华为云Astro Canvas大屏开发研究及指南

本文主要探讨华为云Astro Canvas在数据可视化大屏开发中的应用及效果。首先阐述Astro Canvas的基本概念、功能和特性说明&#xff0c;接着集中分析展示其在教育、金融、交通行业等不同领域实际应用案例&#xff1b;之后&#xff0c;详细介绍使用该工具进行大屏图表创建的开发指…

从零开始 Spring Cloud 15:多级缓存

从零开始 Spring Cloud 15&#xff1a;多级缓存 多级缓存架构 传统的缓存使用 Redis&#xff0c;大致架构如下&#xff1a; 这个架构存在一些问题&#xff1a; 请求要经过Tomcat处理&#xff0c;Tomcat的性能成为整个系统的瓶颈 Redis缓存失效时&#xff0c;会对数据库产生冲…

MySQL实践——分页查询优化

问题现象 一个客户业务系统带有分页查询功能&#xff0c;但是随着查询页数的增加&#xff0c;越往后查询性能越差&#xff0c;有时一个查询可能需要1分钟左右的时间。分页查询的写法类似于&#xff1a; select * from employees limit 250000,5000;这是最传统的一种分页查询写…

Amazon图片下载器:利用Scrapy库完成图像下载任务

概述 本文介绍了如何使用Python的Scrapy库编写一个简单的爬虫程序&#xff0c;实现从Amazon网站下载商品图片的功能。Scrapy是一个强大的爬虫框架&#xff0c;提供了许多方便的特性&#xff0c;如选择器、管道、中间件、代理等。本文将重点介绍如何使用Scrapy的图片管道和代理…

Python爬虫:ad广告引擎的模拟登录

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ &#x1f434;作者&#xff1a;秋无之地 &#x1f434;简介&#xff1a;CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作&#xff0c;主要擅长领域有&#xff1a;爬虫、后端、大数据…

神器抓包工具 HTTP Analyzer v7.5 的下载,安装,使用,破解说明以及可能遇到的问题

文章目录 1、HTTP Analyzer 工具能干什么&#xff1f;2、HTTP Analyzer 如何下载&#xff1f;3、如何安装&#xff1f;4、如何使用&#xff1f;5、如何破解&#xff1f;6、Http AnalyzerStd V7可能遇到的问题 1、HTTP Analyzer 工具能干什么&#xff1f; A1&#xff1a;HTTP A…

Linux:命令行参数和环境变量

文章目录 命令行参数环境变量环境变量的概念常见的环境变量PATH 环境变量表本地变量和环境变量命令分类 本篇主要解决以下问题&#xff1a; 什么是命令行参数命令行参数有什么用环境变量是什么环境变量存在的意义 命令行参数 在学习C语言中&#xff0c;对于main函数当初的写…

(二)docker:建立oracle数据库mount startup

这章其实我想试一下startup部分做mount&#xff0c;因为前一章在建完数据库容器后&#xff0c;需要手动创建用户&#xff0c;授权&#xff0c;建表等&#xff0c;好像正好这部分可以放到startup里&#xff0c;在创建容器时直接做好&#xff1b;因为setup部分我实在没想出来能做…

订水商城H5实战教程-02系统登录

目录 1 创建数据源2 创建自定义应用3 创建全局变量4 实现登录功能5 控制弹窗是否显示6 最终的效果 上一篇我们分析了订水商城的功能&#xff0c;功能分析好了之后&#xff0c;就需要开发功能。用户登录商城的第一步就是进行登录&#xff0c;登录的时候需要同意用户协议&#xf…

SpringBoot AOP + Redis 延时双删功能实战

一、业务场景 在多线程并发情况下&#xff0c;假设有两个数据库修改请求&#xff0c;为保证数据库与redis的数据一致性&#xff0c;修改请求的实现中需要修改数据库后&#xff0c;级联修改Redis中的数据。 请求一&#xff1a;A修改数据库数据 B修改Redis数据 请求二&#xff…

修炼k8s+flink+hdfs+dlink(六:学习k8s-pod)

一&#xff1a;增&#xff08;创建&#xff09;。 直接进行创建。 kubectl run nginx --imagenginx使用yaml清单方式进行创建。 直接创建方式&#xff0c;并建立pod。 kubectl create deployment my-nginx-deployment --imagenginx:latest 先创建employment&#xff0c;不…

CSS页面基本布局

前提回顾 1. 超文本标记语言&#xff08;HTML&#xff09;是一种标记语言&#xff0c;用来结构化我们的网页内容并赋予内容含义&#xff1b; &#xff08;超文本标记语言&#xff08;英语&#xff1a;HyperText Markup Language /ˈhaɪpətekst ˈmɑːkʌp ˈlŋɡwɪdʒ /…

由浅到深 : Self-Attention (自注意力机制)

Self-Attention 看到下面的第一个saw是动词&#xff0c;第二个saw是名词。 因为第一个saw和第二个saw在形式上没有任何差别。如果任务是进行词性的判断&#xff0c;把上面的词直接输入给神经网络&#xff0c;那么它肯定不能够正确分析。 想要正确分析词性&#xff0c;那么该…

CRM自动化意味着什么?企业如何从中受益?

客户关系管理&#xff08;CRM&#xff09;软件不再仅仅适用于大公司或销售周期长的行业&#xff0c;它越来越成为各种规模企业的重要工具。 在日常工作中&#xff0c;当你陷入流程的所有细节时&#xff0c;可能会产生不必要的工作。因此&#xff0c;如果你想要CRM提供的组织和…

Redis的持久化策略:RDB与AOF(面试题详解)

文章来源&#xff1a;Redis持久化的两种方式&#xff1a;RDB与AOF&#xff08;详解&#xff09;&#xff0c;订正了一些错误 一、概述&#xff1a; RDB和AOF持久化的由来&#xff1f; 因为Redis中的数据是基于内存的&#xff0c;所以如果出现服务器断电或者服务器宕机&#xf…

数据结构堆详解

[TOC]堆详解 一&#xff0c;堆 1.1堆的概念 堆的性质&#xff1a; 堆中某个节点的值总是不大于或不小于其父节点的值&#xff1b; 堆总是一棵完全二叉树。 1.2堆的存储模式 我们前面的文章提到过&#xff0c;二叉树的两种存储模式&#xff0c;一个是顺序存储&#xff0c;一…

【Java集合类面试八】、 介绍一下HashMap底层的实现原理

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a; 介绍一下HashMap底层的…

华为OD技术面试-最短距离矩阵(动态规划、广度优先)

背景 记录2023-10-21 晚华为OD三面的手撕代码题&#xff0c;当时没做出来&#xff0c;给面试官说了我的想法&#xff0c;评价&#xff1a;解法复杂了&#xff0c;只是简单的动态规范 或 广度优先算法&#xff0c;事后找资料记录实现方式。 题目 腐烂的橘子 问题描述&#xff…

怎样找外企/远程的工作

“如果你既不想卷&#xff0c;又不想参与职场的勾心斗角&#xff0c;也不算行业大牛&#xff0c;还不愿意冒太高风险&#xff0c;那还有一种渠道&#xff0c;就是找海外公司的远程工作&#xff0c;比如我有几个程序员朋友&#xff0c;都是拿着硅谷动辄 20w 刀的薪水&#xff0c…