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

news2024/11/18 3:02:38

一、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];
    //空间清0
    memset(arr, 0, sizeof(int)*capacity);
}
Array::Array(int capacity)
{
    this‐>capacity = capacity;
    size = 0;
    arr = new int[capacity];
    //空间清0
    memset(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.coloradmin.cn/o/1125057.html

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

相关文章

【SwiftUI模块】0060、SwiftUI基于Firebase搭建一个类似InstagramApp 2/7部分-搭建TabBar

SwiftUI模块系列 - 已更新60篇 SwiftUI项目 - 已更新5个项目 往期Demo源码下载 技术:SwiftUI、SwiftUI4.0、Instagram、Firebase 运行环境: SwiftUI4.0 Xcode14 MacOS12.6 iPhone Simulator iPhone 14 Pro Max SwiftUI基于Firebase搭建一个类似InstagramApp 2/7部分-搭建Tab…

构建离线应用:Apollo与本地状态管理

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…

网络流探索:解决网络最大流问题的算法集锦

1.初识网络流 网络流一直是初学者心中很难过去的一道坎&#xff0c;很多人说它是一个不像DFS/BFS那么直观的算法&#xff0c;同时网上也有各种参差不齐的材料&#xff0c;让人感到一知半解。 如果你也有这样的感觉&#xff0c;那么不要灰心&#xff0c;坚持住&#xff0c;因为…

【仙逆】王林用计灭富二代,有长命锁也没用,藤化元一怒请一人出山

【侵权联系删除】【文/郑尔巴金】 仙逆动漫第七集已经更新了。而这一集看下来&#xff0c;可以说非常精彩&#xff0c;全程在打&#xff0c;期间还能看到主角王林用谋&#xff0c;是如何一步步的把敌人藤厉引入陷阱灭杀的&#xff0c;更可以看到王林是如何筑基的。那么多的不说…

Windows系统下安装CouchDB3.3.2教程

安装 前往CouchDB官网 官网点击download下载msi文件 双击该msi文件&#xff0c;一直下一步 创建个人account 设置cookie value 用于进行身份验证和授权。 愉快下载 点击OK 重启 启动 重启电脑后 打开浏览器并访问以下链接&#xff1a;http://127.0.0.1:5984/ 如果没有问…

SQL UPDATE 语句(更新表中的记录)

SQL UPDATE 语句 UPDATE 语句用于更新表中已存在的记录。 还可以使用AND或OR运算符组合多个条件。 SQL UPDATE 语法 具有WHERE子句的UPDATE查询的基本语法如下所示&#xff1a; UPDATE table_name SET column1 value1, column2 value2, ... WHERE conditi…

编写第一个python程序

实践流程 新建程序 ↓选择“file”\"new feile"命令 向世界问好 ↓print&#xff08;‘hello word’&#xff09; 保存&#xff0c;运行程序 ↓按“F5键”运行程序 修改程序 ↓print(hello word\n *20) 常见错误 中文错误 熟悉python idle编程环境 学习流程…

Go学习第五章——函数与包

Go学习第五章——函数与包 1 函数1.1 基本语法1.2 函数多返回值1.3 函数的可见性和包级函数1.4 函数调用机制底层原理1.5 值类型和引用类型1.6 注意事项和细节1.7 逃逸机制&#xff08;补&#xff0c;可不看&#xff09; 2 包2.1 快速入门2.2 包的使用细节 3 函数详细讲解3.1 递…

3BHE009319R0001 UNS2881b-P,V1 l展示面向边缘人工智能应用

3BHE009319R0001 UNS2881b-P,V1 l展示面向边缘人工智能应用 ASRock Industrial展示了由第12代英特尔酷睿处理器(Alder Lake-P)支持的NUC 1200 BOX/iBOX 1200系列工业计算机&#xff0c;用于跨行业的人工智能加速。工业计算机采用高达12个内核/16个线程的高性能混合架构和高达9…

MySQL -- 库和表的操作

MySQL – 库和表的操作 文章目录 MySQL -- 库和表的操作一、库的操作1.创建数据库2.查看数据库3.删除数据库4.字符集和校验规则5.校验规则对数据库的影响6.修改数据库7.备份和恢复8.查看连接情况 二、表的操作1.创建表2.查看表结构3.修改表4.删除表 一、库的操作 注意&#xf…

针对遗留系统采取的不同演化策略

1. 改造策略 高水平、高价值区&#xff0c;即遗留系统的技术含量较高&#xff0c;本身还有极大的生命力。系统具有较高的业务价值&#xff0c;基本上能够满足企业业务运作和决策支持的需要。这种系统可能建成的时间还很短&#xff0c;对这种遗留系统的演化策略为改造。改造包括…

找不到conda可执行文件:解决方法

1.在新版本的pycharm出现的问题如下&#xff1a; 2.解决方法: 2.1 将anaconda\Scripts\conda.exe选中 2.2选择自己的anconda自己的环境&#xff0c;之后就可以正常创建conda环境

基于Tucker分解的时序知识图谱补全10.23

基于Tucker分解的时序知识图谱补全 摘要引言相关工作静态知识图谱补全时序知识图谱补全 背景提出的模型学习时间复杂度和参数增长表达能力分析 实验 摘要 知识图谱已被证明是众多智能应用的有效工具。然而&#xff0c;大量有价值的知识仍然隐含在知识图谱中。为了丰富现有的知…

异步加载 JavaScript

目录 ​编辑 前言&#xff1a;异步加载 JavaScript 的重要性 详解&#xff1a;异步加载 JavaScript 的方法 使用 使用动态创建标签&#xff1a; 使用模块引入&#xff08;ES6模块&#xff09;&#xff1a; 解析&#xff1a;异步加载 JavaScript 的重要性和优势 实践和注…

后台交互-个人中心->小程序登录微信登录接口演示,小程序授权登录理论,小程序授权登录代码演示,微信表情包存储问题

小程序登录微信登录接口演示小程序授权登录理论小程序授权登录代码演示微信表情包存储问题 1.小程序登录微信登录接口演示 推荐使用 wx.getUserProfile 获取用户信息&#xff0c;开发者每次通过该接口获取用户个人信息均需用户确认 // pages/index/index.js Page({data: {user…

24东北大学计算机计划招生数据

2.结语 24的保研名额很多&#xff0c;统考名额就这些&#xff0c;大家根据自己的情况做出选择 东大计算机不好考&#xff0c;但是不代表考不上&#xff01;加油 3.数据来源于官网 官网链接

基于深度学习实现一张单图,一个视频,一键换脸,Colab脚本使用方法,在线版本,普通人也可以上传一张图片体验机器学习一键换脸

基于深度学习实现一张单图,一个视频,一键换脸,Colab脚本使用方法,在线版本,普通人也可以上传一张图片体验机器学习一键换脸。 AI领域人才辈出,突然就跳出一个大佬“s0md3v”,开源了一个单图就可以进行视频换脸的项目。 项目主页给了一张换脸动图非常有说服力,真是一图…

python网络爬虫(二)基本库的使用urllib/requests

使用urllib 了解一下 urllib 库&#xff0c;它是 Python 内置的 HTTP 请求库&#xff0c;也就是说不需要额外安装即可使用。它包含如下 4 个模块。 request&#xff1a;它是最基本的 HTTP 请求模块&#xff0c;可以用来模拟发送请求。就像在浏览器里输入网址然后回车一样&…

【项目经理】工作流引擎

项目经理之 工作流引擎 一、业务系统管理目的维护信息 二、组织架构管理目的维护信息 三、角色矩阵管理目的维护信息 四、条件变量管理目的维护信息 五、流程模型管理目的维护信息 六、流程版本管理目的维护信息 七、流程监管控制目的维护信息 系列文章版本记录 一、业务系统管…

COS 音视频实践

对象存储 音视频处理概述-媒体处理实践-最佳实践-腾讯云 1、COS https://www.cnblogs.com/cloudstorageangel/p/15977032.html 全程&#xff1a;对象存储&#xff08;Cloud Object Storage&#xff0c;COS&#xff09;&#xff1b;腾讯云提供的对象存储服务。 可以对音视频…