当前位置: 首页 > news >正文

《C++程序设计》笔记p3

C++对象的生命周期

  1. 为对象创建内存
  2. 创建对象的各个成员变量(调用各个成员变量的构造函数)
  3. 调用构造函数初始化对象自身
  4. 使用对象...
  5. 调用析构函数释放对象使用的资源。
  6. 销毁各个程序员变量(调用各个成员变量的析构函数)
  7. 释放内存

析构函数 (Destructor)

作用:释放对象对象使用的资源。

析构函数 会在对象销毁前自动调用。如果类内没有定义析构函数,则编译器也会为其添加一个析构函数,默认的析构函数什么都不做。

析构函数的语法

class 类名{public:~类名(void) {... 做释放内存或关闭文件等操作。}
}

说明:

  • 析构函数只有一个,且不能重载。
  • 析构函数没有参数和返回值。
  • 析构函数会在对象销毁前自动调用。无需手动调用。

全局变量(对象)的构造和析构函数调用规则

全局变量(对象)存在于数据段,而数据段是在 main 函数调用之前创建,并创建数据段内的对象,因此全局变量(对象)的构造函数会先用main调用。同样析构函数也会在 main 函数结束后调用。

构造函数的传参语法

类名 对象名;  // 调用无参的构造函数
类名 对象名(实参列表);  // 调用有参的构造函数,根据重载规则匹配构造函数
类名 对象名 = 值;  // 调用一个参数的构造函数(同时根据重载匹配规则)

int i = 0;  //等同于 int i(0);

示例代码

#include <iostream>
#include <stdlib.h>
#include <string.h>using namespace std;// 定义一个MyString类,使用动态数组来存储字符信息
class MyString {public:// 将字符串初始化成 n个内容为 c的字符MyString(char c, int n) {cout << "MyString(" << c << "," << n<<")\n";data = (char*)malloc(n+1);for (int i = 0; i < n; i++) {data[i] = c;}data[n] = '\0';}MyString(const char * p=""):data(NULL) {cout << "MyString(" << p << ")\n";// 计算传入参数的长度int str_len = strlen(p);data = (char*)malloc(str_len+1);strcpy(data, p);}// 析构函数~MyString(){cout << "~MyString(" << data << ")" << endl;free(data);}private:char * data;
};int main(int argc, char * argv[]) {MyString s1;  // 调用无参数的构造函数MyString s2('x', 10);  // 根据重载规则调用两个参数的构造函数。MyString s3("name1"); // 调用一个参数的构造函数MyString s4 = "name2"; // 调用一个参数的构造函数cout << sizeof(s1) << endl;cout << "程序结束!" << endl;return 0;
}// MyString x1("world");
// MyString x2("1111");

new 和 delete 关键字

作用:在堆上创建对象和释放对象 。

C 语言分配内存的方法: malloc/free

C++ 创建对象的方法: new / delete

  • new 分配内存,同时调用构造函数
  • delete 调用析构函数,然后释放内存

语法

// 创建单个对象
new 类名;  // 调用无参数的构造函数
new 类名(实参列表); // 根据重载规则调用有参数的构造函数// 创建对象数组
new 类名[对象个数(整数)]
// 创建对象数组,并指定构造函数
new 类名[对象个数(整数)]{每个对象的初始化构造函数}// 销毁单个对象
delete 对象地址
// 销毁对象数组
delete [] 对象地址

深拷贝和浅拷贝

浅拷贝:是指在复制对象的过程中,对象的每个成员都依次赋值给新对象的成员各个成员。

对象的默认复制是浅拷贝

深拷贝:是指在复制对象的过程中,每个对象的资源都各自独立,不共用,成为独立的个体。

拷贝构造函数(copy construtor)

作用:是进行深拷贝

语法格式

class 类名{类名(const 类名 & src){}
};

说明:

  • 拷贝构造数是C类的缺省构造函数。如果不写此构造函数。C 默认生成一个缺省的构造函数。默认执行浅拷贝

示例代码

#include <stdlib.h>
#include <string.h>using namespace std;// 定义一个MyString类,使用动态数组来存储字符信息
class MyString {public:// 将字符串初始化成 n个内容为 c的字符MyString(char c, int n) {cout << "MyString(" << c << "," << n<<")\n";data = (char*)malloc(n+1);for (int i = 0; i < n; i++) {data[i] = c;}data[n] = '\0';}MyString(const char * p=""):data(NULL) {cout << "MyString(" << p << ")\n";// 计算传入参数的长度int str_len = strlen(p);data = (char*)malloc(str_len+1);strcpy(data, p);}// 拷贝构造函数,对指针执向的内容进行深度复制MyString(const MyString & src) {cout << "MyString(const MyString& src.data:" << src.data << ")\n";// 求源对象字符的长度int str_len = strlen(src.data);data = (char*) malloc(str_len+1);strcpy(data, src.data);}// 析构函数~MyString(){cout << "~MyString(" << data << ")" << endl;free(data);}const char * c_str(void) {return data;}private:char * data;
};int main(int argc, char * argv[]) {MyString s1 = "zhangsan";MyString s2 = s1;  // 调用拷贝构造函数MyString s3(s2);  // 调用拷贝构造函数cout << "s1:" << s1.c_str() << endl;cout << "s2:" << s2.c_str() << endl;cout << "程序结束!" << endl;return 0;
}

示例:

给MyString添加两个成员函数

class MyString{public:void copy(const char * content) {...}void copy(const MyString & src) {...}
};

使其修改 data 执行的内容,让器变为新的内容

参考

#include <iostream>
#include <stdlib.h>
#include <string.h>using namespace std;// 定义一个MyString类,使用动态数组来存储字符信息
class MyString {public:// 将字符串初始化成 n个内容为 c的字符MyString(char c, int n) {cout << "MyString(" << c << "," << n<<")\n";data = (char*)malloc(n+1);for (int i = 0; i < n; i++) {data[i] = c;}data[n] = '\0';}MyString(const char * p=""):data(NULL) {cout << "MyString(" << p << ")\n";// 计算传入参数的长度int str_len = strlen(p);data = (char*)malloc(str_len+1);strcpy(data, p);}// 拷贝构造函数,对指针执向的内容进行深度复制MyString(const MyString & src) {cout << "MyString(const MyString& src.data:" << src.data << ")\n";// 求源对象字符的长度int str_len = strlen(src.data);data = (char*) malloc(str_len+1);strcpy(data, src.data);}// 析构函数~MyString(){cout << "~MyString(" << data << ")" << endl;free(data);}const char * c_str(void) {return data;}private:char * data;public:// 要求不能有内存泄漏void copy(const char * content) {// 释放自己原有的内存free(data);int str_len = strlen(content);data = (char*)malloc(str_len+1);strcpy(data, content);}void copy(const MyString & src){// 释放自己原有的内存free(data);int str_len = strlen(src.data);data = (char*)malloc(str_len+1);strcpy(data, src.data);}
};int main(int argc, char * argv[]) {MyString s1 = "zhangsan";MyString s2;s2.copy(s1);cout << "s1:" << s1.c_str() << endl; // zhangsancout << "s2:" << s2.c_str() << endl; // zhangsans2.copy("lisi");cout << "s2:" << s2.c_str() << endl; // lisi cout << "程序结束!" << endl;return 0;
}

C++ 成员函数的调用方式:

语法

对象.函数名(参数列表)
对象指针->函数名(参数列表)

面向对象编程(OOP)

OOP(Object Oriented Programming)

类:对象的描述(蓝图)

对象:类创建的实例,真正占用内存的变量。

思想:用类来描述对象的行为。用类封装对象数据。

描述方法:

有两个人(Human),张三(zhang3) 和 李四(li3)张三工作赚钱 1000 元
李四借张三 300 元
李四买游戏机花了270元;
张三教李四玩王者荣耀
李四教张三 C++用面相对象的思想来描述。

示例代码:

#include <iostream>
#include <stdlib.h>
#include <string.h>using namespace std;class Human {public:Human(const char * n) : name(n),money(0){}void showInfo(void) {cout << name << ", 有钱:" << money << "元, 技能:" << skill << endl;}void work(int m) {money += m;cout << name << " 工作赚了" << m << "元,共有"  << money << "元" << endl;}void borrowFrom(Human & h, int m) {if (m > h.money) {cout << h.name << "没有" << m << "元这么多钱,借钱失败!" << endl;return;}h.money -= m;money += m;cout << h.name << "借给" << name << m << "元钱!" << endl;}private:string name;int money;string skill; // 技能 :w};int main(int argc, char * argv[]) {// 有两个人(Human),张三(zhang3) 和 李四(li3)Human zhang3("张三");Human li4("李四");// 张三工作赚钱 1000 元// zhang3.work(1000);// 李四借张三 300 元li4.borrowFrom(zhang3, 300);zhang3.showInfo();li4.showInfo();
//    // 李四买游戏机花了270元;
//    li4.buy("游戏机", 270);
//    // 李四教张三玩王者荣耀
//    li4.teach(zhang3, "王者荣耀");
//    // 张三教李四 C++
//    zhang3.teach(li4, "C++");cout << "程序结束!" << endl;return 0;
}
http://www.dtcms.com/a/393280.html

相关文章:

  • 华为数字化转型战略框架:从“1套方法+4类场景+3个平台”的全景设计
  • Redis:主从复制与哨兵模式解析
  • 【中压选型篇】中压电源进线与变压器选型全指南:从拓扑设计到并联运行
  • 【精品资料鉴赏】数据治理咨询项目实施方案
  • 基于陌讯AIGC检测算法的局限性探讨:最大512Token输入下的长文本处理方案
  • 应用随机过程(三)
  • A/B测试:随机化与观察单位不一致,如何处理更科学
  • 树拍易购商业模式解析:创新与合规并行的数实融合样本
  • 使用递归求阶乘的和
  • HTML 结构与常用标签
  • AI 智能体开发工作流从哪些方面入手?
  • USBL与DVL数据融合的实时定位系统,MATLAB仿真
  • 端到端与世界模型(1):自动驾驶的基础模型从 VLM 到 VLA
  • Let’s Encrypt 免费SSL证书一键获取 - 网页版极简教程
  • IDEA指定配置文件启动
  • Python实现基于教学的优化器 (Teaching-Learning-Based Optimization, TLBO) (附完整代码)
  • 视频图像数据档案管理
  • 灰狼优化算法GWO
  • 2025csp入门组真题和解析
  • Keil-MDK程序运行和下载过程
  • 【Linux驱动】Linux字符设备框架
  • python、数据结构
  • 数字孪生能做什么?(续)
  • C++指针:高效编程的核心钥匙
  • WIN11操作系统安装PL2303TA USB转串口驱动问题
  • ​​[硬件电路-280]:两相步进电机的功能、四个接口信号与工作原理详解(电能转化为机械能)
  • conda换源
  • 博客系统UI自动化测试报告
  • 大语言模型 LLM 通过 Excel 知识库 增强日志分析,根因分析能力的技术方案(6):vLLM 为什么能够成为企业级推理事实上的标准?
  • Redis最佳实践——秒杀系统设计详解