C++新手入门学习教程(完整版)
以下教程覆盖了 C++ 学习的各个方面,适合初学者循序渐进地学习。学习过程中,建议初学者多做练习和项目,以加深对理论知识的理解。希望这个教程能为你提供一个清晰的学习路径。
目录
第一章:C++ 简介
1.1 C++ 的历史与演变
1.2 C++ 的特点和优势
1.3 C++ 的应用领域
1.4 C++ 的未来展望
第二章:环境搭建
2.1 安装 C++ 编译器与 IDE
Windows
Linux
Mac
2.2 配置开发环境
2.3 编译与运行示例程序
第三章:基本语法
3.1 C++ 程序结构
3.2 注释的使用
3.3 数据类型与变量
示例
3.4 常量与输入输出
第四章:控制结构
4.1 条件语句
if 语句示例
switch 语句示例
4.2 循环结构
for 循环示例
do-while 循环示例
第五章:函数
5.1 函数的定义与调用
5.2 参数传递方式
5.3 函数重载
5.4 默认参数与 inline 函数
5.5 Lambda表达式与函数对象
第六章:数组与字符串
6.1 一维数组与多维数组
一维数组示例
多维数组示例
6.2 字符串的处理
6.3 常用字符串函数
第七章:指针与引用
7.1 指针的概念与使用
7.2 指针与数组的关系
7.3 引用的概念与使用
7.4 指针与动态内存分配
第八章:结构体与联合体
8.1 结构体的定义与使用
8.2 结构体数组
8.3 联合体的定义与使用
8.4 枚举类型的使用
第九章:类与对象
9.1 面向对象的基本概念
9.2 类的定义与对象的创建
9.3 构造函数与析构函数
9.4 成员函数与属性
9.5 访问控制
第十章:继承与多态
10.1 继承的概念与实现
10.2 基类与派生类
10.3 虚函数与多态
10.4 多态的实现
第十一章:模板与泛型编程
11.1 函数模板
11.2 类模板
11.3 模板特化
11.4 STL(标准模板库)简介
第十二章:异常处理
12.1 异常的概念
12.2 try, catch, throw 语句
12.3 自定义异常类
示例:定义自定义异常类
代码解析
额外信息
第十三章:文件操作
13.1 文件的读写操作
示例:写入文件
示例:读取文件
13.2 二进制文件与文本文件
示例:写入二进制文件
示例:读取二进制文件
13.3 文件流的使用
示例
第十四章:标准库与命名空间
14.1 C++ 标准库概述
14.2 常用标准库函数与算法
示例:使用 vector
示例:使用 algorithm 库
14.3 命名空间的使用
第十五章:高级特性
15.1 智能指针的使用
示例:使用 std::unique_ptr
15.2 Lambda 表达式与并发编程
示例:使用 Lambda 表达式
15.3 C++11/14/17/20 新特性
第十六章:综合项目
16.1 项目设计与结构
16.2 代码实现与管理
16.3 代码调试与优化
第十七章:学习资源与实践
17.1 推荐书籍
17.2 在线课程
17.3 开源项目与参与
17.4 C++ 社区与论坛
第十八章:附录
18.1 C++ 关键字
18.2 常用函数与算法汇总
18.3 参考文献
第一章:C++ 简介
1.1 C++ 的历史与演变
C++ 由 Bjarne Stroustrup 在 1979 年开始开发,最初被称为 "C with Classes",以扩展 C 语言的功能。1985 年发布了第一个完整版本,并随后的标准化过程使其不断演化。C++ 的标准化版本包括 C++98、C++03、C++11、C++14、C++17 和 C++20。
1.2 C++ 的特点和优势
- 面向对象编程:支持封装、继承和多态,提高代码的可重用性。
- 高效性:为系统层面的编程提供了高效的内存管理机制。
- 标准模板库 (STL):包含丰富的算法和数据结构,极大地提高了开发效率。
- 多范式支持:支持过程式、面向对象和泛型编程。
1.3 C++ 的应用领域
- 系统软件:操作系统、编译器和网络系统。
- 应用软件:桌面应用、数据库和图形用户界面。
- 游戏开发:高性能游戏引擎,如 Unreal Engine。
- 嵌入式系统:汽车、家电和机器人设计。
1.4 C++ 的未来展望
随着技术的不断发展,C++ 正在与时俱进,越来越多的特性(如概念和协程)正在被引入,以满足现代开发的需求。社区对于可维护性和安全性的关注也在增加。
第二章:环境搭建
2.1 安装 C++ 编译器与 IDE
Windows
- MinGW:轻量级的编译器,简单易用。
- Visual Studio:功能强大的 IDE,适合 Windows 开发。
Linux
- 使用命令:
sudo apt-get install g++
或sudo yum install gcc-c++
。
Mac
- 使用 Homebrew:
brew install gcc
。
2.2 配置开发环境
确保将编译器添加到系统路径中。可使用命令行工具或终端进行编译和运行。
2.3 编译与运行示例程序
创建一个名为 hello.cpp
的文件,内容如下:
#include <iostream>
using namespace std;int main() {cout << "Hello, C++!" << endl; // 输出 "Hello, C++!"return 0; // 返回 0,表示程序正常结束
}
在命令行中,使用以下命令编译并运行程序:
g++ hello.cpp -o hello
./hello
第三章:基本语法
3.1 C++ 程序结构
一个基本的 C++ 程序通常包括头文件、主函数和必要的逻辑。
3.2 注释的使用
使用注释可以提高代码的可读性。
// 这是单行注释
/* 这是多行注释可以跨越多行 */
3.3 数据类型与变量
数据类型
C++ 为程序员提供了种类丰富的内置数据类型和用户自定义的数据类型。下表列出了七种基本的
类型 | 关键字 |
---|---|
布尔型 | bool |
字符型 | char |
整型 | int |
浮点型 | float |
双浮点型 | double |
无类型 | void |
宽字符型 | wchar_t |
其实 wchar_t 是这样来的:
typedef short int wchar_t;
所以 wchar_t 实际上的空间是和 short int 一样。
一些基本类型可以使用一个或多个类型修饰符进行修饰:
- signed
- unsigned
- short
- long
下表显示了各种变量类型在内存中存储值时需要占用的内存,以及该类型的变量所能存储的最大值和最小值。
注意:不同系统会有所差异,一字节为 8 位。
注意:默认情况下,int、short、long都是带符号的,即 signed。
注意:long int 8 个字节,int 都是 4 个字节,早期的 C 编译器定义了 long int 占用 4 个字节,int 占用 2 个字节,新版的 C/C++ 标准兼容了早期的这一设定。
类型 | 位 | 范围 |
---|---|---|
char | 1 个字节 | -128 到 127 或者 0 到 255 |
unsigned char | 1 个字节 | 0 到 255 |
signed char | 1 个字节 | -128 到 127 |
int | 4 个字节 | -2147483648 到 2147483647 |
unsigned int | 4 个字节 | 0 到 4294967295 |
signed int | 4 个字节 | -2147483648 到 2147483647 |
short int | 2 个字节 | -32768 到 32767 |
unsigned short int | 2 个字节 | 0 到 65,535 |
signed short int | 2 个字节 | -32768 到 32767 |
long int | 8 个字节 | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 |
signed long int | 8 个字节 | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 |
unsigned long int | 8 个字节 | 0 到 18,446,744,073,709,551,615 |
float | 4 个字节 | 精度型占4个字节(32位)内存空间,+/- 3.4e +/- 38 (~7 个数字) |
double | 8 个字节 | 双精度型占8 个字节(64位)内存空间,+/- 1.7e +/- 308 (~15 个数字) |
long long | 8 个字节 | 双精度型占8 个字节(64位)内存空间,表示 -9,223,372,036,854,775,807 到 9,223,372,036,854,775,807 的范围 |
long double | 16 个字节 | 长双精度型 16 个字节(128位)内存空间,可提供18-19位有效数字。 |
wchar_t | 2 或 4 个字节 | 1 个宽字符 |
注意,各种类型的存储大小与系统位数有关,但目前通用的以64位系统为主。
以下列出了32位系统与64位系统的存储大小的差别(windows 相同):
从上表可得知,变量的大小会根据编译器和所使用的电脑而有所不同。
下面实例会输出您电脑上各种数据类型的大小。
示例
#include<iostream>
#include <limits>using namespace std; int main()
{ cout << "type: \t\t" << "************size**************"<< endl; cout << "bool: \t\t" << "所占字节数:" << sizeof(bool); cout << "\t最大值:" << (numeric_limits<bool>::max)(); cout << "\t\t最小值:" << (numeric_limits<bool>::min)() << endl; cout << "char: \t\t" << "所占字节数:" << sizeof(char); cout << "\t最大值:" << (numeric_limits<char>::max)(); cout << "\t\t最小值:" << (numeric_limits<char>::min)() << endl; cout << "signed char: \t" << "所占字节数:" << sizeof(signed char); cout << "\t最大值:" << (numeric_limits<signed char>::max)(); cout << "\t\t最小值:" << (numeric_limits<signed char>::min)() << endl; cout << "unsigned char: \t" << "所占字节数:" << sizeof(unsigned char); cout << "\t最大值:" << (numeric_limits<unsigned char>::max)(); cout << "\t\t最小值:" << (numeric_limits<unsigned char>::min)() << endl; cout << "wchar_t: \t" << "所占字节数:" << sizeof(wchar_t); cout << "\t最大值:" << (numeric_limits<wchar_t>::max)(); cout << "\t\t最小值:" << (numeric_limits<wchar_t>::min)() << endl; cout << "short: \t\t" << "所占字节数:" << sizeof(short); cout << "\t最大值:" << (numeric_limits<short>::max)(); cout << "\t\t最小值:" << (numeric_limits<short>::min)() << endl; cout << "int: \t\t" << "所占字节数:" << sizeof(int); cout << "\t最大值:" << (numeric_limits<int>::max)(); cout << "\t最小值:" << (numeric_limits<int>::min)() << endl; cout << "unsigned: \t" << "所占字节数:" << sizeof(unsigned); cout << "\t最大值:" << (numeric_limits<unsigned>::max)(); cout << "\t最小值:" << (numeric_limits<unsigned>::min)() << endl; cout << "long: \t\t" << "所占字节数:" << sizeof(long); cout << "\t最大值:" << (numeric_limits<long>::max)(); cout << "\t最小值:" << (numeric_limits<long>::min)() << endl; cout << "unsigned long: \t" << "所占字节数:" << sizeof(unsigned long); cout << "\t最大值:" << (numeric_limits<unsigned long>::max)(); cout << "\t最小值:" << (numeric_limits<unsigned long>::min)() << endl; cout << "double: \t" << "所占字节数:" << sizeof(double); cout << "\t最大值:" << (numeric_limits<double>::max)(); cout << "\t最小值:" << (numeric_limits<double>::min)() << endl; cout << "long double: \t" << "所占字节数:" << sizeof(long double); cout << "\t最大值:" << (numeric_limits<long double>::max)(); cout << "\t最小值:" << (numeric_limits<long double>::min)() << endl; cout << "float: \t\t" << "所占字节数:" << sizeof(float); cout << "\t最大值:" << (numeric_limits<float>::max)(); cout << "\t最小值:" << (numeric_limits<float>::min)() << endl; cout << "size_t: \t" << "所占字节数:" << sizeof(size_t); cout << "\t最大值:" << (numeric_limits<size_t>::max)(); cout << "\t最小值:" << (numeric_limits<size_t>::min)() << endl; cout << "string: \t" << "所占字节数:" << sizeof(string) << endl; // << "\t最大值:" << (numeric_limits<string>::max)() << "\t最小值:" << (numeric_limits<string>::min)() << endl; cout << "type: \t\t" << "************size**************"<< endl; return 0;
}
本实例使用了 endl,这将在每一行后插入一个换行符,<< 运算符用于向屏幕传多个值,sizeof() 运算符用来获取各种数据类型的大小。
当上面的代码被编译和执行时,它会产生以下的结果,结果会根据所使用的计算机而有所不同:
type: ************size**************
bool: 所占字节数:1 最大值:1 最小值:0
char: 所占字节数:1 最大值: 最小值:?
signed char: 所占字节数:1 最大值: 最小值:?
unsigned char: 所占字节数:1 最大值:? 最小值:
wchar_t: 所占字节数:4 最大值:2147483647 最小值:-2147483648
short: 所占字节数:2 最大值:32767 最小值:-32768
int: 所占字节数:4 最大值:2147483647 最小值:-2147483648
unsigned: 所占字节数:4 最大值:4294967295 最小值:0
long: 所占字节数:8 最大值:9223372036854775807 最小值:-9223372036854775808
unsigned long: 所占字节数:8 最大值:18446744073709551615 最小值:0
double: 所占字节数:8 最大值:1.79769e+308 最小值:2.22507e-308
long double: 所占字节数:16 最大值:1.18973e+4932 最小值:3.3621e-4932
float: 所占字节数:4 最大值:3.40282e+38 最小值:1.17549e-38
size_t: 所占字节数:8 最大值:18446744073709551615 最小值:0
string: 所占字节数:24
type: ************size**************
变量类型
基本的变量类型如下:
基于前一章讲解的基本类型,有以下几种基本的变量类型,将在下一章中进行讲解:
类型 | 描述 |
---|---|
bool | 布尔类型,存储值 true 或 false,占用 1 个字节。 |
char | 字符类型,用于存储 ASCII 字符,通常占用 1 个字节。 |
int | 整数类型,通常用于存储普通整数,通常占用 4 个字节。 |
float | 单精度浮点值,用于存储单精度浮点数。单精度是这样的格式,1 位符号,8 位指数,23 位小数,通常占用4个字节。 |
double | 双精度浮点值,用于存储双精度浮点数。双精度是 1 位符号,11 位指数,52 位小数,通常占用 8 个字节。 |
void | 表示类型的缺失。 |
wchar_t | 宽字符类型,用于存储更大范围的字符,通常占用 2 个或 4 个字节。 |
C++ 也允许定义各种其他类型的变量,比如枚举、指针、数组、引用、数据结构、类等等,这将会在后续的章节中进行讲解。
-
整数类型(Integer Types):
int
:用于表示整数,通常占用4个字节。short
:用于表示短整数,通常占用2个字节。long
:用于表示长整数,通常占用4个字节。long long
:用于表示更长的整数,通常占用8个字节。
-
浮点类型(Floating-Point Types):
float
:用于表示单精度浮点数,通常占用4个字节。double
:用于表示双精度浮点数,通常占用8个字节。long double
:用于表示更高精度的浮点数,占用字节数可以根据实现而变化。
-
字符类型(Character Types):
char
:用于表示字符,通常占用1个字节。wchar_t
:用于表示宽字符,通常占用2或4个字节。char16_t
:用于表示16位Unicode字符,占用2个字节。char32_t
:用于表示32位Unicode字符,占用4个字节。
-
布尔类型(Boolean Type):
bool
:用于表示布尔值,只能取true
或false
。
-
枚举类型(Enumeration Types):
enum
:用于定义一组命名的整数常量。
-
指针类型(Pointer Types):
type*
:用于表示指向类型为type
的对象的指针。
-
数组类型(Array Types):
type[]
或type[size]
:用于表示具有相同类型的元素组成的数组。
-
结构体类型(Structure Types):
struct
:用于定义包含多个不同类型成员的结构。
-
类类型(Class Types):
class
:用于定义具有属性和方法的自定义类型。
-
共用体类型(Union Types):
union
:用于定义一种特殊的数据类型,它可以在相同的内存位置存储不同的数据类型。
在 C++ 中,类型的长度(即占用的字节数)取决于编译器和计算机架构,然而,C++ 标准规定了不同整数类型的最小范围,而不是具体的字节数,这是为了确保代码在不同的系统上都能正确运行。
请注意,以上类型的范围只是 C++ 标准规定的最小要求,实际上,许多系统上这些类型可能占用更多的字节,例如,很多现代计算机上 int 通常占用 4 字节,而 long 可能占用 8 字节。
3.4 常量与输入输出
使用 const
关键字定义常量。
const float gravity = 9.81; // 定义常量
使用 cin
和 cout
进行输入输出:
#include <iostream>
using namespace std;int main() {int number;cout << "请输入一个数字: ";cin >> number; // 从用户输入读取数字cout << "你输入的数字是: " << number << endl; // 输出用户输入的数字return 0;
}
第四章:控制结构
4.1 条件语句
if 语句示例
int a = 10;
if (a > 0) {cout << "a 是正数" << endl; // 如果 a 大于 0
} else {cout << "a 不是正数" << endl; // 否则
}
switch 语句示例
int day = 4;
switch (day) {case 1:cout << "星期一" << endl;break;case 2:cout << "星期二" << endl;break;default:cout << "不是工作日" << endl;
}
4.2 循环结构
for 循环示例
for (int i = 0; i < 5; i++) {cout << "i 的值: " << i << endl; // 输出 i 的值
}
while 循环示例
int j = 0;
while (j < 5) {cout << "j 的值: " << j << endl; // 输出 j 的值j++;
}
do-while 循环示例
int k = 0;
do {cout << "k 的值: " << k << endl; // 输出 k 的值k++;
} while (k < 5);
第五章:函数
5.1 函数的定义与调用
函数用于将代码逻辑模块化,便于重用。
int add(int a, int b) {return a + b; // 返回 a 和 b 的和
}int main() {int result = add(5, 3); // 调用函数cout << "5 + 3 = " << result << endl;return 0;
}
5.2 参数传递方式
- 值传递:将参数的副本传递给函数。
- 引用传递:将参数的引用传递给函数(可以修改原变量)。
void modify(int &num) {num += 10; // 修改引用参数 }int main() {int x = 5;modify(x);cout << "x 的值: " << x << endl; // 输出 15return 0; }
5.3 函数重载
允许同名函数,但参数类型或数量不同。
float multiply(float a, float b) {return a * b; }int multiply(int a, int b) {return a * b; }
5.4 默认参数与 inline 函数
- 默认参数示例:
void greet(string name = "World") {cout << "Hello, " << name << "!" << endl; }
inline 函数示例:
inline int square(int x) {return x * x; }
5.5 Lambda表达式与函数对象
使用 lambda 表达式定义简单的函数。
auto add = [](int a, int b) {return a + b; };cout << "Lambda add: " << add(5, 3) << endl; // 输出 8
第六章:数组与字符串
6.1 一维数组与多维数组
一维数组示例
int arr[5] = {1, 2, 3, 4, 5}; for (int i = 0; i < 5; i++) {cout << arr[i] << " "; // 输出数组元素 }
多维数组示例
int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}}; for (int i = 0; i < 2; i++) {for (int j = 0; j < 3; j++) {cout << matrix[i][j] << " "; // 输出矩阵元素} }
6.2 字符串的处理
- C 风格字符串:以
\0
结尾的字符数组。 - C++ 字符串:使用
std::string
。#include <string>string str = "Hello, World!"; cout << "字符串长度: " << str.length() << endl; // 输出字符串长度
6.3 常用字符串函数
string str = "Hello"; str += " World"; // 连接字符串 cout << str << endl; // 输出 "Hello World"
第七章:指针与引用
7.1 指针的概念与使用
指针是存储变量地址的变量。
int a = 10; int *p = &a; // p 存储 a 的地址 cout << "a 的值: " << *p << endl; // 输出 10
7.2 指针与数组的关系
数组名代表数组的首地址,可以用指针访问数组元素。
int arr[3] = {1, 2, 3}; int *p = arr; // 等价于 int *p = &arr[0]; cout << *(p + 1) << endl; // 输出 2
7.3 引用的概念与使用
引用是变量的别名。
int b = 20; int &r = b; // r 是 b 的引用 r = 30; // 修改 r 也会修改 b cout << "b 的值: " << b << endl; // 输出 30
7.4 指针与动态内存分配
使用
new
和delete
进行动态内存管理。int *ptr = new int; // 动态分配内存 *ptr = 42; cout << "动态内存中的值: " << *ptr << endl; delete ptr; // 释放内存
第八章:结构体与联合体
8.1 结构体的定义与使用
结构体用于将不同类型的数据组合在一起。
struct Person {string name;int age; };Person p; p.name = "Alice"; p.age = 30; cout << "姓名: " << p.name << ", 年龄: " << p.age << endl;
8.2 结构体数组
创建结构体数组以存储多个结构体实例。
Person people[2] = {{"Alice", 30}, {"Bob", 25}}; for (int i = 0; i < 2; i++) {cout << "姓名: " << people[i].name << ", 年龄: " << people[i].age << endl; }
8.3 联合体的定义与使用
联合体用于节省内存,所有成员共享相同的内存。
union Data {int intValue;float floatValue; };Data data; data.intValue = 10; cout << "整数值: " << data.intValue << endl; data.floatValue = 5.5; // 修改 floatValue 会影响 intValue 的值 cout << "浮点值: " << data.floatValue << endl;
8.4 枚举类型的使用
枚举用于定义一组命名的整数常量。
enum Color { RED, GREEN, BLUE }; Color c = GREEN; cout << "选择的颜色值: " << c << endl; // 输出 1
第九章:类与对象
9.1 面向对象的基本概念
类是对象的蓝图,对象是类的实例。
9.2 类的定义与对象的创建
class Car { public:string brand;int year;void display() {cout << "品牌: " << brand << ", 年份: " << year << endl;} };int main() {Car myCar;myCar.brand = "Toyota";myCar.year = 2020;myCar.display();return 0; }
9.3 构造函数与析构函数
构造函数用于初始化对象,析构函数用于清理资源。
class Point { public:int x, y;Point(int xVal, int yVal) : x(xVal), y(yVal) {} // 构造函数~Point() {} // 析构函数 };Point p(10, 20); // 创建对象时调用构造函数
9.4 成员函数与属性
类的成员函数可以访问和修改类的属性。
class Circle { public:double radius;double area() {return 3.14 * radius * radius; // 计算面积} };Circle c; c.radius = 5; cout << "圆的面积: " << c.area() << endl; // 输出 78.5
9.5 访问控制
C++ 提供了三种访问控制:public、private、protected。
class Box { private:double width; // 私有属性public:void setWidth(double w) {width = w; // 通过公有方法访问私有属性}double getWidth() {return width;} };
第十章:继承与多态
10.1 继承的概念与实现
继承允许一个类从另一个类派生,重用代码。
class Animal { public:void eat() {cout << "Eating..." << endl;} };class Dog : public Animal { // Dog 继承 Animal public:void bark() {cout << "Barking..." << endl;} };int main() {Dog d;d.eat(); // 调用基类方法d.bark(); // 调用派生类方法return 0; }
10.2 基类与派生类
基类提供公共接口,派生类扩展或修改基类的行为。
10.3 虚函数与多态
虚函数允许在派生类中重写基类的方法。
class Base { public:virtual void show() { // 虚函数cout << "Base class" << endl;} };class Derived : public Base { public:void show() override { // 重写cout << "Derived class" << endl;} };int main() {Base* b = new Derived();b->show(); // 输出 "Derived class"delete b;return 0; }
10.4 多态的实现
通过基类指针调用派生类的重写方法。
Base* basePtr = new Derived(); basePtr->show(); // 输出 "Derived class" delete basePtr;
第十一章:模板与泛型编程
11.1 函数模板
函数模板允许编写可以处理不同数据类型的函数。
template <typename T> T add(T a, T b) {return a + b; }int main() {cout << "int: " << add(5, 10) << endl; // 输出 15cout << "double: " << add(5.5, 3.5) << endl; // 输出 9.0return 0; }
11.2 类模板
类模板允许定义可以处理不同数据类型的类。
template <typename T> class Pair { private:T first, second; public:Pair(T a, T b) : first(a), second(b) {}T getFirst() { return first; }T getSecond() { return second; } };int main() {Pair<int> p(10, 20);cout << "First: " << p.getFirst() << ", Second: " << p.getSecond() << endl;return 0; }
11.3 模板特化
可以为特定类型创建模板特化。
template <> class Pair<string> { private:string first, second; public:Pair(string a, string b) : first(a), second(b) {}string getConcatenated() { return first + second; } };int main() {Pair<string> p("Hello", " World");cout << "Concatenated: " << p.getConcatenated() << endl;return 0; }
11.4 STL(标准模板库)简介
STL 提供了许多通用数据结构和算法,如
vector
,list
,map
,set
等。#include <vector>int main() {vector<int> vec = {1, 2, 3, 4, 5};for (int num : vec) {cout << num << " "; // 输出 1 2 3 4 5}return 0; }
第十二章:异常处理
12.1 异常的概念
异常处理用于处理运行时错误,确保程序的稳定性。
12.2 try, catch, throw 语句
使用
try
块捕获异常,使用catch
块处理异常。try {throw runtime_error("发生错误"); } catch (const runtime_error& e) {cout << "捕获到异常: " << e.what() << endl; // 输出异常信息 }
12.3 自定义异常类
在 C++ 中,你可以根据需要自定义异常类,以提供更具体的错误信息,增强程序的可读性和可维护性。自定义异常类通常继承自
std::exception
类,并重写what()
方法,以提供错误描述。示例:定义自定义异常类
#include <iostream> #include <exception> #include <string>using namespace std;// 自定义异常类,继承自 std::exception class MyException : public std::exception { private:string message; // 错误信息public:// 构造函数MyException(const string& msg) : message(msg) {}// 重写 what() 方法virtual const char* what() const noexcept override {return message.c_str(); // 返回错误信息} };// 函数,可能会抛出异常 void riskyFunction(int value) {if (value < 0) {throw MyException("负数错误:不能为负数"); // 抛出自定义异常}cout << "输入的值是: " << value << endl; }int main() {try {riskyFunction(-1); // 调用可能抛出异常的函数} catch (const MyException& e) {cout << "捕获到异常: " << e.what() << endl; // 输出异常信息} catch (const std::exception& e) {cout << "捕获到标准异常: " << e.what() << endl;}return 0; }
代码解析
-
自定义异常类
MyException
:- 继承自
std::exception
类。 - 在构造函数中接受一个字符串参数,表示错误信息。
- 重写
what()
方法,返回错误信息字符串。
- 继承自
-
函数
riskyFunction
:- 接受一个整数参数。
- 如果参数小于 0,则抛出
MyException
异常。
-
主函数:
- 使用
try
块调用riskyFunction
。 - 如果抛出
MyException
异常,使用catch
块捕获并处理异常,打印出异常信息。
- 使用
额外信息
- 异常安全性:在设计代码时,确保在抛出异常时不会导致资源泄漏或不一致的状态。使用 RAII(资源获取即初始化)技术可以帮助管理资源。
- 异常层次结构:可以创建更复杂的异常层次结构,允许捕获不同类型的异常,提供更详细的错误处理机制。
通过自定义异常类,您可以为程序中的错误和异常情况提供更清晰和更具体的处理方式。这种方法可以提高代码的可读性,并使调试过程更容易。
第十三章:文件操作
13.1 文件的读写操作
示例:写入文件
#include <fstream>
#include <iostream>
using namespace std;int main() {ofstream outFile("example.txt"); // 创建输出文件流if (outFile.is_open()) {outFile << "Hello, file!" << endl; // 写入内容outFile.close(); // 关闭文件} else {cout << "无法打开文件进行写入。" << endl;}return 0;
}
示例:读取文件
#include <fstream>
#include <iostream>
using namespace std;int main() {ifstream inFile("example.txt"); // 创建输入文件流string line;if (inFile.is_open()) {while (getline(inFile, line)) { // 按行读取文件cout << line << endl; // 输出每一行}inFile.close(); // 关闭文件} else {cout << "无法打开文件进行读取。" << endl;}return 0;
}
13.2 二进制文件与文本文件
- 文本文件:以人类可读的格式存储数据。
- 二进制文件:以二进制格式存储数据,通常用于高效存储和读取。
示例:写入二进制文件
#include <fstream>
using namespace std;int main() {ofstream outFile("binary.dat", ios::binary); // 创建二进制输出文件流int num = 42;outFile.write(reinterpret_cast<char*>(&num), sizeof(num)); // 写入整数outFile.close();return 0;
}
示例:读取二进制文件
#include <fstream>
#include <iostream>
using namespace std;int main() {ifstream inFile("binary.dat", ios::binary); // 创建二进制输入文件流int num;inFile.read(reinterpret_cast<char*>(&num), sizeof(num)); // 读取整数cout << "读取的数: " << num << endl;inFile.close();return 0;
}
13.3 文件流的使用
C++ 提供 fstream
,用于同时读取和写入文件。
示例
#include <fstream>
#include <iostream>
using namespace std;int main() {fstream file("example.txt", ios::in | ios::out | ios::app); // 以读写模式打开文件if (file.is_open()) {file << "追加内容!" << endl; // 追加内容file.seekg(0); // 将文件指针移到文件开头string line;while (getline(file, line)) { // 读取文件内容cout << line << endl;}file.close(); // 关闭文件}return 0;
}
第十四章:标准库与命名空间
14.1 C++ 标准库概述
C++ 标准库包含了丰富的函数、类和模板,极大地提高了开发效率。常用的 STL 组件有容器、算法和迭代器。
14.2 常用标准库函数与算法
示例:使用 vector
#include <iostream>
#include <vector>
using namespace std;int main() {vector<int> vec = {1, 2, 3, 4, 5};vec.push_back(6); // 添加元素for (int num : vec) {cout << num << " "; // 输出每个元素}cout << endl;return 0;
}
示例:使用 algorithm
库
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;int main() {vector<int> vec = {5, 3, 1, 4, 2};sort(vec.begin(), vec.end()); // 排序for (int num : vec) {cout << num << " "; // 输出已排序的元素}cout << endl;return 0;
}
14.3 命名空间的使用
命名空间用于组织代码,避免命名冲突。
namespace MyNamespace {void display() {cout << "Hello from MyNamespace!" << endl;}
}int main() {MyNamespace::display(); // 调用命名空间中的函数return 0;
}
第十五章:高级特性
15.1 智能指针的使用
智能指针自动管理内存,减少内存泄漏的风险。
示例:使用 std::unique_ptr
#include <iostream>
#include <memory>
using namespace std;int main() {unique_ptr<int> ptr(new int(10)); // 创建智能指针cout << "值: " << *ptr << endl; // 输出值// 不需要手动 delete,ptr 超出作用域后会自动释放内存return 0;
}
示例:使用 std::shared_ptr
#include <iostream>
#include <memory>
using namespace std;int main() {shared_ptr<int> p1(new int(20)); // 创建共享指针{shared_ptr<int> p2 = p1; // 共享所有权cout << "值: " << *p2 << endl; // 输出值} // p2 超出作用域后不会释放内存,p1 仍然存在cout << "值: " << *p1 << endl; // 输出值return 0;
}
15.2 Lambda 表达式与并发编程
Lambda 表达式用于简化函数对象的定义,适合回调和并行执行。
示例:使用 Lambda 表达式
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;int main() {vector<int> vec = {1, 2, 3, 4, 5};for_each(vec.begin(), vec.end(), [](int n) {cout << n << " "; // 输出每个元素});cout << endl;return 0;
}
15.3 C++11/14/17/20 新特性
- C++11:引入了
auto
关键字、范围 for 循环、nullptr、线程库等。 - C++14:改进了 lambda 表达式,支持泛型 lambda。
- C++17:引入了结构化绑定、if constexpr、std::optional 等。
- C++20:引入了概念(concept)、范围(ranges)等。
第十六章:综合项目
16.1 项目设计与结构
设计一个小型项目,定义功能模块与类结构,使用面向对象的设计原则。
16.2 代码实现与管理
使用版本控制工具(如 Git)管理代码,记录每次更新。
16.3 代码调试与优化
使用调试工具(如 GDB 或 IDE 内置调试工具)进行调试,分析性能瓶颈并进行优化。
第十七章:学习资源与实践
17.1 推荐书籍
- 《C++ Primer》 - Stanley B. Lippman
- 《Effective C++》 - Scott Meyers
- 《The C++ Programming Language》 - Bjarne Stroustrup
- 《高质量程序设计指南-C++\C语言》第三版
17.2 在线课程
- Coursera、edX、Udacity 等平台的 C++ 课程。
- B站的编程教程频道。
17.3 开源项目与参与
参与 GitHub 上的 C++ 开源项目,学习最佳实践,提升编程能力。
17.4 C++ 社区与论坛
加入 C++ 相关的社区与讨论组(如 Stack Overflow、Reddit 的 C++ 版块),向他人学习。
第十八章:附录
18.1 C++ 关键字
列出 C++ 中的所有关键字,比如 class
, public
, private
, virtual
, template
等。
18.2 常用函数与算法汇总
- 排序:
sort()
- 查找:
find()
- 复制:
copy()
- 变换:
transform()
18.3 参考文献
- C++ 标准文档
- 各大编程网站的相关教程与文档。
这个C++ 学习教程,可以帮助初学者系统地掌握 C++ 语言的基础与进阶知识,同时提供了丰富的示例和练习,结合项目实践,有助于巩固所学的知识。希望对你有所帮助!
相关文章:

C++新手入门学习教程(完整版)
以下教程覆盖了 C 学习的各个方面,适合初学者循序渐进地学习。学习过程中,建议初学者多做练习和项目,以加深对理论知识的理解。希望这个教程能为你提供一个清晰的学习路径。 目录 第一章:C 简介 1.1 C 的历史与演变 1.2 C 的特…...

Python 爬虫入门(六):urllib库的使用方法
Python 爬虫入门(六):urllib库的使用方法 前言1. urllib 概述2. urllib.request 模块2.1 发送GET请求2.2 发送POST请求2.3 添加headers2.4 处理异常 3. urllib.error 模块4. urllib.parse 模块4.1 URL解析4.2 URL编码和解码4.3 拼接URL 5. ur…...

个人开发神器,一应俱全,有你想要的!
哈喽,各位小伙伴们好,我是给大家带来各类黑科技与前沿资讯的小武。 经常有很多小伙伴问小武,是从哪里获取到这么多资源,其实除了熟知的吾爱、酷安等知名论坛集聚地,还有一些强大的资源聚合类软件也非常重要。 如之前安…...
电子电气架构 --- SOVD在域控制器的应用
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…...

React(四):DOCX文件在线预览
效果 注意 ⚠️注意:部分文件预览存在问题 依赖 $ yarn add docx-preview $ yarn add jszip源码 import ./index.scss; import {useRef} from react; import type {UploadRequestOption} from rc-upload/lib/interface; import {Upload, Button, message} from an…...

Java IO.字符集,流,缓冲流 转换流 对象操作流
一.字符集 如果使用字节流 , 把文本文件中的内容读取到内存时, 可能会出现乱码 如果使用字节流 , 把中文写入文本文件中 , 也有可能会出现乱码 读取n.txt"你好" 两个汉字 字节流读中文,每次只能读一部分所以出现了乱码 字符集(Character se…...

线性稳压器的内部电路与构成分析
线性稳压器的一般的引脚构成 线性稳压器基本上由VIN (输入)、VO (输出)、GND (接地)三个引脚构成。在输出可变的线性稳压器上添加了用于反馈输出电压的FB(反馈引脚)。 简单来说&am…...

Go语言实现多协程文件下载器
文章目录 前言流程图主函数下载文件初始化分片下载worker分发下载任务获取下载文件的大小下载文件分片错误重试项目演示最后 前言 你好,我是醉墨居士,最近在开发文件传输相关的项目,然后顺手写了一个多协程文件下载器,代码非常精…...
本地方法详解
本地方法(Native Methods)是指那些由Java程序调用,但其实现是用非Java语言(如C、C等)编写的方法。它们通常用于访问操作系统底层的功能或进行高效的计算,这些是Java本身不能直接实现的。下面详细解释本地方…...
每日新闻掌握【2024年8月3日 星期六】
2024年8月3日 星期六 农历六月廿九 大公司/大事件 微信地震预警全国上线 36氪获悉,国家地震烈度速报与预警工程已于7月25日正式通过国家验收。8月2日,在中国地震局指导下,中国地震台网中心、中央广播电视总台国家应急广播与腾讯联合推出“中…...

python入门基础篇(一)
基础篇 Python基础安装与配置Python环境理解Python解释器第一个Python程序:"Hello, World!" 基础语法注释与文档字符串变量与数据类型数字类型:整数、浮点数、复数字符串布尔值None值 运算符算术运算符比较运算符逻辑运算符赋值运算符位运算符…...

windows下在线预览服务kkFileView4.4.0问题记录
前几天找到一个开源项目:kkFileView,感觉可能以后可能会用到,所以尝试了下。 通过git下载下来,版本是4.4.0,通过idea打开项目,发现老是无法找到组件aspose-cad,版本是23.9. 找了好多文章&#x…...
Java:通过反射获取class类的属性
有如下一个普通类,我想获取他的所有属性值 package com.demo.bean;import lombok.Data;import java.util.List;Data public class UserBean {private String name;private Integer age;private List<String> tags; }可以通过反射的方式获取属性值 package c…...

07.FreeRTOS列表与列表项
文章目录 07. FreeRTOS列表与列表项1. 列表和列表项的简介2. 列表相关API函数3. 代码验证 07. FreeRTOS列表与列表项 1. 列表和列表项的简介 列表的定义: typedef struct xLIST {listFIRST_LIST_INTEGRITY_CHECK_VALUE /* 校验值 */volatile UBaseType_t uxN…...
餐饮业油烟净化器安装势在必行,切勿侥幸
我最近分析了餐饮市场的油烟净化器等产品报告,解决了餐饮业厨房油腻的难题,更加方便了在餐饮业和商业场所有需求的小伙伴们。 随着环保法规的日益严格和公众环保意识的提升,餐饮业油烟排放问题成为社会关注的焦点。油烟不仅影响环境质量&am…...

SpringBoot集成阿里百炼大模型 原子的学习日记Day01
文章目录 概要下一章SpringBoot集成阿里百炼大模型(多轮对话) 原子的学习日记Day02 整体架构流程技术名词解释集成步骤1,选择大模型以及获取自己的api-key(前面还有一步开通服务就没有展示啦!)2,…...

【网络编程】网络原理(一)
系列文章目录 1、 初识网络 2、网络编程的基础使用(一) 文章目录 系列文章目录前言一、端口号的使用二、UDP报文学习1.报文格式2.MD5算法 总结 前言 在前文中,主要对UDP和TCP协议有了简单的了解,而这两种协议是负责传输层的内容…...

鲁班上门维修安装系统源码开发之功能模式
鲁班上门维修安装系统在当今的趋势呈现出显著的增长与创新。随着物联网、智能家居的普及,以及消费者对便捷、高效生活方式的追求,鲁班上门维修安装系统凭借其多渠道预约、智能派单、在线支付与费用明细透明等优势,赢得了市场的广泛认可。 …...
图数据处理的新时代:阿里FraphCompute与蚂蚁金服TuGraph对比综述
目录 前言 阿里FraphCompute与蚂蚁金服TuGraph的主要特性和功能的比较: 阿里FraphCompute与蚂蚁金服TuGraph在不同应用场景分析对比: 阿里FraphCompute与蚂蚁金服TuGraph未来趋势的对比: FraphCompute与TuGraph详解 缺点劣势深入比较 前言…...

InnoDB引擎下SQL的执行流程
SQL执行流程 连接器 客户端连接驱动与mysql连接池连接 半双工通信传入客户端的sql 查询缓存(8.0之后没有) 删除原因 如果每次查询条件不同导致命中率低没有命中缓存 创建新缓存在创建缓存的时候会添加表级锁缓存更新需要批量失效 sql解析器 对传入的sql 词法分析 分解成各种t…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...

地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...

现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...