2025-07-21
C++
00

通讯录管理系统

1、系统需求

通讯录是一个可以记录亲人、好友信息的工具。

本教程主要利用C++来实现一个通讯录管理系统

系统中需要实现的功能如下:

  • 添加联系人:向通讯录中添加新人,信息包括(姓名、性别、年龄、联系电话、家庭住址)最多记录1000人
  • 显示联系人:显示通讯录中所有联系人信息
  • 删除联系人:按照姓名进行删除指定联系人
  • 查找联系人:按照姓名查看指定联系人信息
  • 修改联系人:按照姓名重新修改指定联系人
  • 清空联系人:清空通讯录中所有信息
  • 退出通讯录:退出当前使用的通讯录

2、创建项目

创建项目步骤如下:

  • 创建新项目
  • 添加文件

2.1 创建项目

打开vs2017后,点击创建新项目,创建新的C++项目

img

2025-07-21
C++
00

C++基础入门

1 C++初识

1.1 第一个C++程序

编写一个C++程序总共分为4个步骤

  • 创建项目
  • 创建文件
  • 编写代码
  • 运行程序

1.1.1 创建项目

​ Visual Studio是我们用来编写C++程序的主要工具,我们先将它打开

img img img

1.1.2 创建文件

右键源文件,选择添加->新建项

img

给C++文件起个名称,然后点击添加即可。

img

2025-07-20
C++
00

10.移动语义与资源管理

移动语义与智能指针

移动语义

为什么要用移动语义?

我们回顾一下之前模拟的String.cc

cpp
展开代码
#include <string.h> #include <iostream> using std::cout; using std::endl; class String { public: // 默认构造函数:初始化空字符串 String() : _pstr(new char[1]()) { cout << "String()" << endl; } // 有参构造函数:接受 C 风格字符串并复制 String(const char *pstr) : _pstr(new char[strlen(pstr) + 1]()) { cout << "String(const char *)" << endl; strcpy(_pstr, pstr); } // 拷贝构造函数:深拷贝字符串 String(const String &rhs) : _pstr(new char[strlen(rhs._pstr) + 1]()) { cout << "String(const String &)" << endl; strcpy(_pstr, rhs._pstr); } // 赋值操作符重载:深拷贝字符串并处理自我赋值 String &operator=(const String &rhs) { cout << "String &operator=(const String &)" << endl; if (this != &rhs) { if (_pstr) { delete[] _pstr; // 删除旧的内存 } _pstr = new char[strlen(rhs._pstr) + 1](); // 分配新内存 strcpy(_pstr, rhs._pstr); // 拷贝内容 } return *this; } // 获取字符串长度 size_t length() const { size_t len = 0; if (_pstr) { len = strlen(_pstr); } return len; } // 返回 C 风格字符串 const char *c_str() const { if (_pstr) { return _pstr; } else { return nullptr; } } // 析构函数:释放分配的内存 ~String() { cout << "~String()" << endl; if (_pstr) { delete[] _pstr; _pstr = nullptr; } } // 打印字符串内容 void print() const { if (_pstr) { cout << "_pstr = " << _pstr << endl; } else { cout << endl; } } private: char * _pstr; // 存储 C 风格字符串的指针 }; // 测试函数:演示 String 类的使用 void test0() { String s1("hello"); // 使用有参构造函数 // 拷贝构造 String s2 = s1; // 使用临时对象创建 s3,并深拷贝 String s3 = "hello"; }

创建s3的过程中实际创建了一个临时对象,也会在堆空间上申请一片空间,然后把字符串内容复制给s3的pstr,这一行结束时临时对象的生命周期结束,它申请的那片空间被回收。这片空间申请了,又马上被回收,实际上可以视作一种不必要的开销。我们希望能够少new一次,可以直接将s3能够复用临时对象申请的空间。

这其实也可以视为是一种隐式转换。

2025-07-20
C++
00

9.模板

第九章 模板

模板是一种通用的描述机制,使用模板允许使用通用类型来定义函数或类。在使用时,通用类型可被具体的类型,如 int、double 甚至是用户自定义的类型来代替。模板引入一种全新的编程思维方式,称为“泛型编程”或“通用编程”。

为什么要定义模板

像C/C++/Java等语言,是编译型语言,先编译后运行。它们都有一个强大的类型系统,也被称为强类型语言,希望在程序执行之前,尽可能地发现错误,防止错误被延迟到运行时。所以会对语言本身的使用造成一些限制,称之为静态语言。与之对应的,还有动态语言,也就是解释型语言。如javascript/python/Go,在使用的过程中,一个变量可以表达多种类型,也称为弱类型语言。因为没有编译的过程,所以相对更难以调试。

如图,变量a表达了int数据,然后又去表达了字符串,python中允许这样的做法。

强类型程序设计中,参与运算的所有对象的类型在编译时即确定下来,并且编译程序将进行严格的类型检查。为了解决强类型的严格性和灵活性的冲突,也就是在严格的语法要求下尽可能提高灵活性,有以下3种方式:

例如,想要实现能够处理各种类型参数的加法函数

2025-07-20
C++
00

8.多态

第八章 多态

  1. 什么叫多态?

多态( polymorphism )是面向对象设计语言的基本特征之一。仅仅是将数据和函数捆绑在一起,进行类的封装,使用一些简单的继承,还不能算是真正应用了面向对象的设计思想。多态是面向对象的精髓。多态可以简单地概括为“一个接口,多种方法”。比如说:警车鸣笛,普通人反应一般,但逃犯听见会大惊失色,拔腿就跑。

通常是指对于同一个消息、同一种调用,在不同的场合,不同的情况下,执行不同的行为 。

  1. 为什么需要多态性?

我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类)。它们的目的都是为了代码重用。而多态除了代码的复用性外,还可以解决项目中紧偶合的问题,提高程序的可扩展性。

如果项目耦合度很高的情况下,维护代码时修改一个地方会牵连到很多地方,会无休止的增加开发成本。而降低耦合度,可以保证程序的扩展性。而多态对代码具有很好的可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。

C++支持两种多态性:编译时多态和运行时多态。

编译时多态:也称为静态多态,我们之前学习过的函数重载运算符重载就是采用的静态多态,C++编译器根据传递给函数的参数和函数名决定具体要使用哪一个函数,又称为静态联编。

运行时多态:在一些场合下,编译器无法在编译过程中完成联编,必须在程序运行时完成选择,因此编译器必须提供这么一套称为“动态联编”(dynamic binding)的机制,也叫动态联编。C++通过虚函数来实现动态联编。接下来,我们提到的多态,不做特殊说明,指的就是动态多态