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


    目录

    一、new和delete 堆区空间操作

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

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

     3、new和delete操作类的空间

     4、new申请操作对象数组

     二、静态成员

    1、概念

    2、静态成员数据

     3、静态成员函数

     三、单例模式

    四、类的存储结构

    五、this指针

    六、const修饰成员函数 

    七、友元

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

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

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

    4、案例

    (1)遥控器的类

    (2)动态数组类


     

    一、new和delete 堆区空间操作

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

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

     区别:

    new 不用强制类型转换

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

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

     3、new和delete操作类的空间

     4、new申请操作对象数组

     二、静态成员

    1、概念

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

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

    1. class Data
    2. {
    3. int a;//普通成员数据
    4. static int a;//静态成员数据
    5. static void func()//静态成员函数
    6. {
    7. }
    8. };

    2、静态成员数据

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

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

    1. #pragma warning(disable:4996)
    2. #include<iostream>
    3. using namespace std;
    4. class Data
    5. {
    6. public:
    7. int mA;//普通成员数据
    8. static int count;//静态成员数据
    9. public:
    10. Data()
    11. {
    12. count++;
    13. }
    14. Data(int a)
    15. {
    16. mA = a;
    17. count++;
    18. }
    19. Data(const Data &ob)
    20. {
    21. count++;
    22. }
    23. ~Data()
    24. {
    25. count--;
    26. }
    27. };
    28. //类外初始化
    29. int Data::count = 0;
    30. void test()
    31. {
    32. Data ob1;
    33. Data ob2(10);
    34. Data ob3 = ob2;
    35. cout << "对象个数:" << Data::count << endl;//3
    36. {
    37. Data ob4;
    38. Data ob5;
    39. cout << "对象个数:" << Data::count << endl;//5
    40. }
    41. cout << "对象个数:" << Data::count << endl;//3
    42. }
    43. int main(int argc, char* argv[])
    44. {
    45. test();
    46. return 0;
    47. }

     3、静态成员函数

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

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

     三、单例模式

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

            核心:将构造函数私有化

    1. #include <iostream>
    2. using namespace std;
    3. class SingleTon//单例模式
    4. {
    5. //构造私有化 防止实例化其他对象
    6. private:
    7. SingleTon(){
    8. count=0;
    9. cout<<"构造"<<endl;
    10. }
    11. SingleTon(const SingleTon &ob){
    12. count=0;
    13. }
    14. ~SingleTon()
    15. {
    16. cout<<"析够"<<endl;
    17. }
    18. private:
    19. //const防止p 在类内部 被修改指向
    20. static SingleTon * const p;//保存唯一的实例地址
    21. int count;//统计任务执行次数
    22. public:
    23. static SingleTon * getSingleTon(void)//获取唯一的实例地址
    24. {
    25. return p;
    26. }
    27. //用户自定义 任务函数
    28. void printString(char *str)
    29. {
    30. count++;
    31. cout<<"当前第"<<count<<"次任务打印:"<<str<<endl;
    32. }
    33. };
    34. SingleTon *const SingleTon::p = new SingleTon;//创建唯一的实例
    35. int main(int argc, char *argv[])
    36. {
    37. //获取单例的地址
    38. SingleTon *p1 =SingleTon::getSingleTon();
    39. //执行任务
    40. p1>printString("学历证明1");
    41. p1>printString("身份证明1");
    42. SingleTon *p2 =SingleTon::getSingleTon();
    43. p2>printString("学历证明2");
    44. p2>printString("身份证明2");
    45. }

    四、类的存储结构

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

    五、this指针

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

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

            this可以完成链式操作 

    六、const修饰成员函数 

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

    七、友元

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

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

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

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

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

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

    1. #pragma warning(disable:4996)
    2. #include<iostream>
    3. #include <string>
    4. using namespace std;
    5. class room;//向前声明,只能说明类名称
    6. class Frind
    7. {
    8. public:
    9. void visiting01(Room& room);
    10. void visiting02(Room& room);
    11. };
    12. class Room
    13. {
    14. friend void goodGay::visiting02(Room &room);
    15. private:
    16. string bedroom;//实例化对象
    17. public:
    18. string livingroom;
    19. public:
    20. Room(string bedroom,string livingroom)
    21. {
    22. this-> bedroom = bedroom;
    23. this-> livingroom = livingroom;
    24. }
    25. };
    26. void test()
    27. {
    28. Room room("我的卧室", "我的客厅");
    29. Frind ob;
    30. ob.visiting01(room);
    31. ob.visiting02(room);
    32. }
    33. int main(int argc, char* argv[])
    34. {
    35. test();
    36. return 0;
    37. }
    38. void Frind::visiting01(Room& room)
    39. {
    40. cout << "李四访问到" << room.livingroom << endl;
    41. //cout<<"李四访问到"<<room.bedRoom<<endl;该成员函数不是类的友元,报错
    42. }
    43. void Frind::visiting02(Room& room)
    44. {
    45. cout << "好基友张三访问到" << room.livingroom << endl;
    46. cout << "好基友张三访问到" << room.bedroom << endl;
    47. }

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

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

    1. #pragma warning(disable:4996)
    2. #include<iostream>
    3. #include <string>
    4. using namespace std;
    5. class room;//向前声明,只能说明类名称
    6. class Frind
    7. {
    8. public:
    9. void visiting01(Room& room);
    10. void visiting02(Room& room);
    11. };
    12. class Room
    13. {
    14. friend class Frind;
    15. private:
    16. string bedroom;//实例化对象
    17. public:
    18. string livingroom;
    19. public:
    20. Room(string bedroom,string livingroom)
    21. {
    22. this-> bedroom = bedroom;
    23. this-> livingroom = livingroom;
    24. }
    25. };
    26. void test()
    27. {
    28. Room room("我的卧室", "我的客厅");
    29. Frind ob;
    30. ob.visiting01(room);
    31. ob.visiting02(room);
    32. }
    33. int main(int argc, char* argv[])
    34. {
    35. test();
    36. return 0;
    37. }
    38. void Frind::visiting01(Room& room)
    39. {
    40. cout << "李四访问到" << room.livingroom << endl;
    41. cout<<"李四访问到"<<room.bedRoom<<endl;
    42. }
    43. void Frind::visiting02(Room& room)
    44. {
    45. cout << "好基友张三访问到" << room.livingroom << endl;
    46. cout << "好基友张三访问到" << room.bedroom << endl;
    47. }

    4、案例

    (1)遥控器的类

    1. #include <iostream>
    2. using namespace std;
    3. class TV;
    4. class Remote//遥控器类
    5. {
    6. private:
    7. TV *p;
    8. public:
    9. Remote(TV *p);
    10. void offOrOn(void);//开关
    11. void upVolume(void);//音量
    12. void downVolume(void);
    13. void upChannel(void);//频道
    14. void downChannel(void);
    15. void showTv(void);
    16. void setChannel(int channel);
    17. };
    18. class TV
    19. {
    20. friend void Remote::setChannel(int channel);
    21. enum{OFF, ON};
    22. enum{minVol, maxVol=10};
    23. enum{minChan, maxChan=25};
    24. private:
    25. int state;
    26. int volume;
    27. int channel;
    28. public:
    29. TV()
    30. {
    31. state = OFF;
    32. volume = minVol;
    33. channel = minChan;
    34. }
    35. void offOrOn(void);
    36. void upVolume(void);
    37. void downVolume(void);
    38. void upChannel(void);
    39. void downChannel(void);
    40. void showTv(void);
    41. };
    42. int main(int argc, char *argv[])
    43. {
    44. //实例化一个电视机
    45. TV tv;
    46. Remote re(&tv);
    47. re.offOrOn();
    48. re.upVolume();
    49. re.upVolume();
    50. re.upVolume();
    51. re.setChannel(20);
    52. re.showTv();
    53. return 0;
    54. }
    55. void TV::offOrOn()
    56. {
    57. state = (state==OFF?ON:OFF);
    58. return;
    59. }
    60. void TV::upVolume()
    61. {
    62. if(volume == maxVol)
    63. {
    64. cout<<"音量已经最大了"<<endl;
    65. return;
    66. }
    67. volume++;
    68. return;
    69. }
    70. void TV::downVolume()
    71. {
    72. if(volume == minVol)
    73. {
    74. cout<<"音量已经最小了"<<endl;
    75. return;
    76. }
    77. volume‐‐;
    78. return;
    79. }
    80. void TV::upChannel()
    81. {
    82. if(channel == maxChan)
    83. {
    84. cout<<"频道已经最大了"<<endl;
    85. return;
    86. }
    87. channel++;
    88. return;
    89. }
    90. void TV::downChannel()
    91. {
    92. if(channel == minChan)
    93. {
    94. cout<<"频道已经最小了"<<endl;
    95. return;
    96. }
    97. channel‐‐;
    98. return;
    99. }
    100. void TV::showTv()
    101. {
    102. cout<<"当前电视机的状态:"<<(state==OFF?"关":"开")<<endl;
    103. cout<<"当前电视机的音量:"<<volume<<endl;
    104. cout<<"当前电视机的频道:"<<channel<<endl;
    105. }
    106. Remote::Remote(TV *p)
    107. {
    108. this‐>p = p;
    109. }
    110. void Remote::offOrOn()
    111. {
    112. p‐>offOrOn();
    113. }
    114. void Remote::upVolume()
    115. {
    116. p‐>upVolume();
    117. }
    118. void Remote::downVolume()
    119. {
    120. p‐>downVolume();
    121. }
    122. void Remote::upChannel()
    123. {
    124. p‐>upChannel();
    125. }
    126. void Remote::downChannel()
    127. {
    128. p‐>downChannel();
    129. }
    130. void Remote::showTv()
    131. {
    132. p‐>showTv();
    133. }
    134. void Remote::setChannel(int channel)
    135. {
    136. p‐>channel = channel;
    137. }

    (2)动态数组类

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

    array.h

    1. #ifndef ARRAY_H
    2. #define ARRAY_H
    3. class Array
    4. {
    5. private:
    6. int *arr;//存放首元素地址
    7. int capacity;//容量
    8. int size;//大小
    9. public:
    10. Array();
    11. Array(int capacity);
    12. Array(const Array &ob);
    13. ~Array();
    14. int getCapacity() const;
    15. int getSize() const;
    16. void printArray(void);
    17. //插入尾部元素
    18. void pushBack(int elem);
    19. //删除尾部元素
    20. void popBack(void);
    21. int &at(int pos);
    22. };
    23. #endif // ARRAY_H

    array.cpp

    1. #include "array.h"
    2. #include<string.h>
    3. #include<iostream>
    4. using namespace std;
    5. int Array::getCapacity() const
    6. {
    7. return capacity;
    8. }
    9. int Array::getSize() const
    10. {
    11. return size;
    12. }
    13. void Array::printArray()
    14. {
    15. int i=0;
    16. for(i=0;i<size; i++)
    17. {
    18. cout<<arr[i]<<" ";
    19. }
    20. cout<<endl;
    21. return;
    22. }
    23. void Array::pushBack(int elem)
    24. {
    25. //判断容器是否满
    26. if(size == capacity)
    27. {
    28. //申请空间
    29. int *tmp = new int[2*capacity];
    30. //将就空间的内容 拷贝到新空间
    31. memcpy(tmp, arr, capacity*sizeof(int));
    32. //释放原有的空间
    33. delete [] arr;
    34. //更新arr的空间
    35. arr = tmp;
    36. //更新容量
    37. capacity = 2*capacity;
    38. }
    39. arr[size]=elem;
    40. size++;
    41. return;
    42. }
    43. void Array::popBack()
    44. {
    45. if(size == 0)
    46. {
    47. cout<<"容量为空"<<endl;
    48. }
    49. else
    50. {
    51. size‐‐;
    52. }
    53. return;
    54. }
    55. int& Array::at(int pos)
    56. {
    57. if(pos<0 || pos >=size)
    58. {
    59. cout<<"访问违法内存"<<endl;
    60. exit(‐1);
    61. }
    62. return arr[pos];
    63. }
    64. Array::Array()
    65. {
    66. capacity = 5;
    67. size = 0;
    68. arr = new int[capacity];
    69. //空间清0
    70. memset(arr, 0, sizeof(int)*capacity);
    71. }
    72. Array::Array(int capacity)
    73. {
    74. this‐>capacity = capacity;
    75. size = 0;
    76. arr = new int[capacity];
    77. //空间清0
    78. memset(arr, 0, sizeof(int)*capacity);
    79. }
    80. Array::Array(const Array &ob)
    81. {
    82. capacity = ob.capacity;
    83. size = ob.size;
    84. //深拷贝
    85. arr = new int[capacity];
    86. memcpy(arr, ob.arr, sizeof(int)*capacity);
    87. }
    88. Array::~Array()
    89. {
    90. if(arr != NULL)
    91. {
    92. delete [] arr;
    93. arr = NULL;
    94. }
    95. }

    main.c

    1. #include <iostream>
    2. #include "array.h"
    3. using namespace std;
    4. int main(int argc, char *argv[])
    5. {
    6. Array ob;
    7. cout<<ob.getCapacity()<<" "<<ob.getSize()<<endl;
    8. ob.pushBack(10);
    9. ob.pushBack(20);
    10. ob.pushBack(30);
    11. ob.pushBack(40);
    12. ob.printArray();
    13. cout<<ob.getCapacity()<<" "<<ob.getSize()<<endl;
    14. ob.pushBack(50);
    15. ob.pushBack(60);
    16. ob.printArray();
    17. cout<<ob.getCapacity()<<" "<<ob.getSize()<<endl;
    18. ob.popBack();
    19. ob.popBack();
    20. ob.printArray();
    21. cout<<ob.getCapacity()<<" "<<ob.getSize()<<endl;
    22. cout<<"arr[2] = "<<ob.at(2)<<endl;
    23. ob.at(2) = 100;
    24. ob.printArray();
    25. return 0;
    26. }

  • 相关阅读:
    二叉树与堆
    数据结构学习笔记(第二章线性表)
    【R语言】生存分析模型
    特殊功能寄存器
    黑苹果入门:必备工具篇
    Spring系列九:Spring 事务
    SAP ABAP BDC录屏 保姆级教程
    Linux【网络】数据链路层
    Linux系统编程系列之条件变量
    使用企业订货系统后的效果|软件定制开发|APP小程序搭建
  • 原文地址:https://blog.csdn.net/m0_75045191/article/details/132134371