引入:从 Makefile 到更现代的构建
上一篇的 Makefile 虽然能自动构建项目,但有几个明显的不足:
- 跨平台困难:Windows 用
MinGW或MSVC,Linux 用GCC,macOS 用Clang,Makefile要为每个平台写不同版本。 - 依赖管理原始:如果项目依赖了第三方库(如
SDL2、OpenGL),找库、配置路径全靠手动。 - 语法简陋:条件判断、循环、函数等高级功能写起来很别扭。

上一篇的 Makefile 虽然能自动构建项目,但有几个明显的不足:
MinGW 或 MSVC,Linux 用 GCC,macOS 用 Clang,Makefile 要为每个平台写不同版本。SDL2、OpenGL),找库、配置路径全靠手动。最后一个阶段项目把现代 C++ 的值语义、标准容器、算法、lambda、文件资源和错误处理组合起来。目标是做一个命令行任务管理器,而不是再手动实现一遍动态数组和字符串。
task add "完成报告" --priority 3
task list
task list --pending
task done 12
task remove 12
task save tasks.txt
task load tasks.txt
无论你多么细心,写出来的程序总会有出错的时候。有些错误编译器能帮你发现(语法错误),有些错误程序运行时才会暴露(逻辑错误)。学会调试——即定位和修复错误——是程序员最重要的技能之一。
调试的方法有很多种,从最简单的 printf 大法,到使用专业的调试器。这篇文章我们会逐一介绍。
printf 手动调试的技巧随着程序变大,手动编译的方式逐渐暴露问题:
gcc -c main.c -o main.o
gcc -c utils.c -o utils.o
gcc -c network.c -o network.o
gcc main.o utils.o network.o -o program
标准算法不直接依赖某一种容器,而是通过迭代器描述元素范围。这让同一算法可以处理数组、vector、list 和其他满足要求的序列。
[first, last)#include <algorithm>
#include <vector>
std::vector<int> values{4, 1, 3, 2};
std::sort(values.begin(), values.end());
C 的函数指针只能表示普通函数地址。C++ 中,普通函数、函数对象、lambda 和成员函数包装都可以成为“可调用对象”,让行为更容易作为参数传递。
const auto square = [](int value) {
return value * value;
};
int result = square(5);
错误处理没有一种方式适合所有场景。C++ 既可以使用返回值,也可以使用异常,还提供 std::optional、std::variant 等类型明确表达“可能没有结果”或“结果有多种形态”。
virtual 关键字的使用多态(Polymorphism)字面意思是「多种形态」。在编程里,它指的是:同一个接口,在不同对象上表现出不同行为。
C++ 中多态有两种常见形式:
在 C 中,为 int 动态数组写好的逻辑不能直接用于 double 或自定义对象,通常要依赖 void *、元素大小和回调函数。C++ 模板把类型作为参数,让编译器为具体类型生成类型安全的代码。
#include <iostream>
#include <string>
template <typename T>
T maximum(const T& a, const T& b) {
return a < b ? b : a;
}
int main() {
std::cout << maximum(3, 7) << '\n';
std::cout << maximum(std::string("cat"), std::string("dog")) << '\n';
}
标准模板库提供了经过广泛使用的容器。学习数据结构实现是为了理解代价和约束;写实际 C++ 程序时,通常应优先使用标准容器,而不是重新实现链表、哈希表或动态数组。
std::vector连续存储、支持随机访问、尾部插入均摊 O(1):
#include <iostream>
#include <vector>
int main() {
std::vector<int> values{1, 2, 3};
values.push_back(4);
for (int value : values) {
std::cout << value << ' ';
}
std::cout << '\n';
}