1. C++语言概述与开发环境搭建
C++作为一门久经考验的系统级编程语言,自1979年诞生以来,始终保持着强大的生命力。它完美融合了C语言的高效性和面向对象编程的抽象能力,在操作系统、游戏引擎、高频交易等对性能要求严苛的领域占据着不可替代的地位。
1.1 为什么选择C++
在当今编程语言百花齐放的时代,C++依然保持着独特的竞争优势:
- 无与伦比的性能:直接操作内存、零成本抽象等特性使其执行效率接近机器码
- 硬件级控制能力:指针和内存管理提供了对系统资源的精细控制
- 多范式支持:同时支持面向过程、面向对象和泛型编程
- 丰富的生态系统:拥有成熟的工具链和庞大的第三方库支持
提示:对于需要极致性能或底层硬件交互的场景(如游戏开发、嵌入式系统),C++通常是首选语言。
1.2 开发环境配置实战
工欲善其事,必先利其器。一个高效的开发环境能显著提升编码体验:
Windows平台推荐配置:
- 安装Visual Studio 2022 Community版(免费)
- 选择"使用C++的桌面开发"工作负载
- 勾选CMake工具和Windows 10/11 SDK
- 安装后创建新项目时选择"控制台应用"
Linux/macOS配置方案:
bash复制# Ubuntu/Debian
sudo apt install g++ build-essential cmake
# macOS
brew install gcc cmake
验证安装:
cpp复制#include <iostream>
using namespace std;
int main() {
cout << "Hello, C++ World!" << endl;
return 0;
}
编译运行:
bash复制g++ hello.cpp -o hello && ./hello
1.3 现代C++标准演进
了解C++标准的发展历程有助于我们更好地利用语言特性:
| 标准版本 | 发布年份 | 重大特性 |
|---|---|---|
| C++98 | 1998 | 首个国际标准,奠定基础 |
| C++11 | 2011 | auto、lambda、智能指针 |
| C++14 | 2014 | 泛型lambda、二进制字面量 |
| C++17 | 2017 | 结构化绑定、filesystem |
| C++20 | 2020 | 概念(concepts)、协程 |
注意:新项目建议至少使用C++17标准,可通过编译选项
-std=c++17启用。
2. C++核心语法深度解析
2.1 输入输出系统详解
C++使用流(stream)进行I/O操作,<iostream>头文件提供了标准输入输出流:
cpp复制#include <iostream>
using namespace std;
int main() {
int age;
double salary;
string name;
cout << "Enter your name: ";
getline(cin, name); // 读取整行
cout << "Enter age and salary: ";
cin >> age >> salary; // 链式输入
cout << fixed << setprecision(2);
cout << "Name: " << name << "\n"
<< "Age: " << age << "\n"
<< "Salary: $" << salary << endl;
return 0;
}
关键点说明:
cin会跳过前导空白符,getline()则读取整行包括空格- 流操作符
<<和>>可链式调用 - 使用
<iomanip>中的格式控制符如fixed、setprecision控制输出格式
2.2 控制结构最佳实践
条件与循环是程序逻辑的基础构件,C++提供了丰富的控制结构:
if-else进阶用法:
cpp复制// 初始化语句可放在if条件中
if (auto it = map.find(key); it != map.end()) {
cout << "Found: " << it->second << endl;
} else {
cout << "Key not found" << endl;
}
范围for循环(C++11):
cpp复制vector<int> nums = {1, 2, 3, 4, 5};
for (int n : nums) { // 值传递
cout << n << " ";
}
for (auto& n : nums) { // 引用传递,可修改元素
n *= 2;
}
switch注意事项:
cpp复制switch (value) {
case 1:
cout << "Case 1" << endl;
break; // 必须显式break
case 2: {
// 复杂逻辑建议使用代码块
int result = process(value);
cout << result << endl;
break;
}
default:
cout << "Unknown" << endl;
}
2.3 函数与重载机制
函数是C++程序的基本模块化单元:
cpp复制// 函数声明
double calculateBMI(double weight, double height);
// 函数定义
double calculateBMI(double weight, double height) {
if (height <= 0) throw invalid_argument("Height must be positive");
return weight / (height * height);
}
// 函数重载
void print(int num) { cout << "Integer: " << num << endl; }
void print(double num) { cout << "Double: " << num << endl; }
void print(const string& str) { cout << "String: " << str << endl; }
函数设计原则:
- 单一职责原则:一个函数只做一件事
- 合理使用const修饰符保护参数
- 对于可能失败的操作,使用异常或错误码明确处理
- 避免过长的参数列表(通常不超过5个)
3. 面向对象编程精髓
3.1 类设计与封装艺术
类是面向对象编程的核心概念,良好的类设计需要考虑:
cpp复制class BankAccount {
private:
string accountNumber;
double balance;
static int totalAccounts; // 类静态成员
public:
// 构造函数使用成员初始化列表
explicit BankAccount(string num, double initial = 0.0)
: accountNumber(num), balance(initial) {
totalAccounts++;
}
// 析构函数
~BankAccount() {
totalAccounts--;
cout << "Account " << accountNumber << " closed" << endl;
}
// 成员函数
void deposit(double amount) {
if (amount <= 0) throw invalid_argument("Amount must be positive");
balance += amount;
}
bool withdraw(double amount) {
if (amount > balance) return false;
balance -= amount;
return true;
}
double getBalance() const { return balance; }
static int getTotalAccounts() { return totalAccounts; }
};
int BankAccount::totalAccounts = 0; // 静态成员初始化
封装要点:
- 使用访问修饰符(private/protected/public)严格控制成员可见性
- 提供必要的getter/setter方法,避免直接暴露数据成员
- 构造函数应确保对象创建后处于有效状态
- 对于资源管理类,需遵循RAII原则
3.2 继承与多态实战
继承是代码复用的重要手段,多态则提供了运行时灵活性:
cpp复制class Shape {
protected:
string name;
int sides;
public:
Shape(string n, int s) : name(n), sides(s) {}
virtual ~Shape() = default; // 虚析构函数
virtual double area() const = 0; // 纯虚函数
virtual void draw() const {
cout << "Drawing a " << name << endl;
}
};
class Circle : public Shape {
double radius;
public:
explicit Circle(double r) : Shape("Circle", 1), radius(r) {}
double area() const override {
return 3.14159 * radius * radius;
}
void draw() const override {
cout << "Drawing circle with radius " << radius << endl;
}
};
class Square : public Shape {
double side;
public:
explicit Square(double s) : Shape("Square", 4), side(s) {}
double area() const override {
return side * side;
}
};
// 多态使用示例
void printArea(const Shape& shape) {
cout << "Area: " << shape.area() << endl;
}
int main() {
Circle c(5.0);
Square s(4.0);
printArea(c); // 输出圆的面积
printArea(s); // 输出正方形面积
Shape* shapes[] = {&c, &s};
for (auto shape : shapes) {
shape->draw(); // 动态绑定
}
}
继承设计原则:
- 优先使用组合而非继承
- 遵循LSP原则(里氏替换原则)
- 基类析构函数应为虚函数
- 使用override关键字明确表示重写
4. 标准模板库(STL)深度探索
4.1 容器类精要
STL容器分为序列容器和关联容器两大类:
序列容器比较:
| 容器 | 特点 | 适用场景 |
|---|---|---|
| vector | 动态数组,随机访问快 | 需要频繁随机访问 |
| deque | 双端队列,头尾操作快 | 队列/栈组合需求 |
| list | 双向链表,插入删除快 | 频繁中间插入删除 |
| forward_list | 单向链表,内存占用小 | 只需要前向遍历 |
| array | 固定大小数组 | 替代C风格数组 |
关联容器选择指南:
| 容器 | 特点 | 适用场景 |
|---|---|---|
| set | 唯一键集合 | 需要检查存在性 |
| multiset | 允许重复键 | 需要统计出现次数 |
| map | 键值对映射 | 字典式访问 |
| multimap | 允许重复键 | 一对多映射 |
| unordered_* | 哈希实现,访问O(1) | 不需要有序访问 |
容器使用示例:
cpp复制// vector基本操作
vector<int> vec = {1, 2, 3};
vec.push_back(4); // 末尾添加
vec.insert(vec.begin(), 0); // 开头插入
vec.erase(vec.begin() + 2); // 删除第三个元素
// map使用
map<string, int> wordCount;
wordCount["hello"] = 1;
wordCount["world"]++;
for (const auto& pair : wordCount) {
cout << pair.first << ": " << pair.second << endl;
}
4.2 算法与迭代器
STL算法通过迭代器与容器交互,提供通用操作:
常用算法示例:
cpp复制vector<int> nums = {3, 1, 4, 1, 5, 9, 2, 6};
// 排序
sort(nums.begin(), nums.end());
// 查找
auto it = find(nums.begin(), nums.end(), 5);
if (it != nums.end()) {
cout << "Found at position: " << distance(nums.begin(), it) << endl;
}
// 去重
nums.erase(unique(nums.begin(), nums.end()), nums.end());
// 变换
vector<int> squares;
transform(nums.begin(), nums.end(), back_inserter(squares),
[](int x) { return x * x; });
// 累加
int sum = accumulate(nums.begin(), nums.end(), 0);
迭代器类别:
- 输入迭代器:只读,单遍扫描
- 输出迭代器:只写,单遍扫描
- 前向迭代器:多遍扫描
- 双向迭代器:可反向移动
- 随机访问迭代器:支持算术运算
5. 内存管理与智能指针
5.1 传统内存管理
C++提供了直接的内存控制能力,但也带来了复杂性:
cpp复制// 动态数组示例
int* createArray(size_t size) {
int* arr = new int[size];
// 初始化...
return arr;
}
void processArray() {
int* myArray = createArray(100);
try {
// 使用数组...
} catch (...) {
delete[] myArray; // 异常时释放内存
throw;
}
delete[] myArray; // 正常释放
}
常见内存问题:
- 内存泄漏:忘记释放分配的内存
- 野指针:访问已释放的内存
- 双重释放:多次释放同一内存
- 内存越界:访问分配范围外的内存
5.2 智能指针解决方案
C++11引入的智能指针可自动管理内存生命周期:
unique_ptr:独占所有权
cpp复制#include <memory>
void uniquePtrDemo() {
unique_ptr<int> up1(new int(10)); // 创建
// auto up1 = make_unique<int>(10); // C++14更好
cout << *up1 << endl; // 解引用
// unique_ptr<int> up2 = up1; // 错误!不能复制
unique_ptr<int> up2 = move(up1); // 转移所有权
if (up1) cout << "up1 owns the object" << endl;
if (up2) cout << "up2 owns the object" << endl;
}
shared_ptr:共享所有权
cpp复制void sharedPtrDemo() {
auto sp1 = make_shared<string>("Shared");
{
auto sp2 = sp1; // 引用计数+1
cout << *sp2 << " use count: " << sp2.use_count() << endl;
} // sp2析构,引用计数-1
cout << *sp1 << " use count: " << sp1.use_count() << endl;
}
weak_ptr:解决循环引用
cpp复制class Node {
public:
shared_ptr<Node> next;
weak_ptr<Node> prev; // 使用weak_ptr避免循环引用
~Node() { cout << "Node destroyed" << endl; }
};
void weakPtrDemo() {
auto node1 = make_shared<Node>();
auto node2 = make_shared<Node>();
node1->next = node2;
node2->prev = node1; // 不会增加引用计数
}
智能指针选择策略:
- 优先使用
unique_ptr,除非需要共享所有权 - 使用
make_shared/make_unique而非直接new(更高效、更安全) - 存在循环引用时使用
weak_ptr - 避免将原生指针与智能指针混用
6. 现代C++特性实战
6.1 类型推导与自动管理
C++11引入的auto和decltype简化了类型处理:
cpp复制// auto基本用法
auto i = 42; // int
auto d = 3.14; // double
auto s = "hello"; // const char*
auto v = {1, 2, 3}; // std::initializer_list<int>
// 用于复杂类型
map<string, vector<int>> complexMap;
auto it = complexMap.find("key"); // 避免写冗长的迭代器类型
// decltype获取表达式类型
int x = 10;
decltype(x) y = 20; // y的类型与x相同(int)
decltype((x)) z = x; // z是int&,因为(x)是左值
// 返回类型后置
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
return t + u;
}
6.2 Lambda表达式深入
Lambda是现代C++函数式编程的核心:
cpp复制// 基本语法
auto simple = [] { cout << "Hello Lambda" << endl; };
simple();
// 带参数和返回类型
auto add = [](int a, int b) -> int { return a + b; };
cout << add(3, 4) << endl;
// 捕获列表详解
int x = 10, y = 20;
auto capture = [x, &y] { // x值捕获,y引用捕获
cout << x << ", " << y << endl;
y++; // 可以修改y,因为它是引用捕获
};
capture();
cout << "After: y = " << y << endl;
// 泛型Lambda(C++14)
auto genericAdd = [](auto a, auto b) { return a + b; };
cout << genericAdd(3, 4.5) << endl; // 7.5
// 在STL算法中的应用
vector<int> nums = {1, 2, 3, 4, 5};
int threshold = 3;
auto count = count_if(nums.begin(), nums.end(),
[threshold](int n) { return n > threshold; });
cout << count << " numbers > " << threshold << endl;
6.3 移动语义与完美转发
C++11引入的移动语义显著提升了性能:
cpp复制class StringWrapper {
char* data;
size_t length;
public:
// 构造函数
explicit StringWrapper(const char* str = "") {
length = strlen(str);
data = new char[length + 1];
strcpy(data, str);
}
// 析构函数
~StringWrapper() { delete[] data; }
// 拷贝构造函数
StringWrapper(const StringWrapper& other) {
length = other.length;
data = new char[length + 1];
strcpy(data, other.data);
}
// 移动构造函数
StringWrapper(StringWrapper&& other) noexcept {
data = other.data;
length = other.length;
other.data = nullptr; // 防止析构时释放
other.length = 0;
}
// 拷贝赋值运算符
StringWrapper& operator=(const StringWrapper& other) {
if (this != &other) {
delete[] data;
length = other.length;
data = new char[length + 1];
strcpy(data, other.data);
}
return *this;
}
// 移动赋值运算符
StringWrapper& operator=(StringWrapper&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
length = other.length;
other.data = nullptr;
other.length = 0;
}
return *this;
}
};
void processString(StringWrapper str) {
// 处理字符串...
}
int main() {
StringWrapper s1("Hello");
StringWrapper s2 = s1; // 调用拷贝构造函数
StringWrapper s3 = move(s1); // 调用移动构造函数
processString(StringWrapper("Temporary")); // 移动构造
processString(move(s2)); // 移动构造
}
完美转发实现通用包装器:
cpp复制template<typename T>
void wrapper(T&& arg) {
// 使用std::forward保持参数原始类型
process(std::forward<T>(arg));
}
// 使用示例
wrapper(42); // 传递右值
int x = 10;
wrapper(x); // 传递左值
7. 实战项目:学生管理系统
7.1 系统设计与类结构
我们实现一个完整的学生管理系统,包含以下功能:
- 添加/删除学生
- 查询学生信息
- 按条件筛选学生
- 数据持久化存储
类设计:
cpp复制class Student {
private:
string id;
string name;
int age;
double gpa;
public:
Student(string id, string name, int age, double gpa);
// getters
string getId() const { return id; }
string getName() const { return name; }
int getAge() const { return age; }
double getGpa() const { return gpa; }
// setters
void setName(string newName) { name = move(newName); }
void setAge(int newAge) { age = newAge; }
void setGpa(double newGpa) { gpa = newGpa; }
void display() const;
};
class StudentManager {
private:
vector<Student> students;
public:
void addStudent(Student student);
bool removeStudent(const string& id);
optional<Student> findStudent(const string& id) const;
vector<Student> filterByAge(int minAge, int maxAge) const;
vector<Student> filterByGpa(double minGpa) const;
void loadFromFile(const string& filename);
void saveToFile(const string& filename) const;
void displayAll() const;
};
7.2 核心功能实现
学生类实现:
cpp复制Student::Student(string id, string name, int age, double gpa)
: id(move(id)), name(move(name)), age(age), gpa(gpa) {
if (age < 0 || age > 120) throw invalid_argument("Invalid age");
if (gpa < 0 || gpa > 4.0) throw invalid_argument("GPA must be 0-4.0");
}
void Student::display() const {
cout << "ID: " << id << "\n"
<< "Name: " << name << "\n"
<< "Age: " << age << "\n"
<< "GPA: " << fixed << setprecision(2) << gpa << "\n"
<< "-----------------\n";
}
学生管理类关键方法:
cpp复制void StudentManager::addStudent(Student student) {
// 检查学号是否已存在
if (any_of(students.begin(), students.end(),
[&](const Student& s) { return s.getId() == student.getId(); })) {
throw runtime_error("Student ID already exists");
}
students.push_back(move(student));
}
bool StudentManager::removeStudent(const string& id) {
auto it = find_if(students.begin(), students.end(),
[&](const Student& s) { return s.getId() == id; });
if (it != students.end()) {
students.erase(it);
return true;
}
return false;
}
optional<Student> StudentManager::findStudent(const string& id) const {
auto it = find_if(students.begin(), students.end(),
[&](const Student& s) { return s.getId() == id; });
if (it != students.end()) {
return *it;
}
return nullopt;
}
vector<Student> StudentManager::filterByGpa(double minGpa) const {
vector<Student> result;
copy_if(students.begin(), students.end(), back_inserter(result),
[minGpa](const Student& s) { return s.getGpa() >= minGpa; });
return result;
}
7.3 数据持久化实现
文件存储与加载:
cpp复制void StudentManager::saveToFile(const string& filename) const {
ofstream out(filename);
if (!out) throw runtime_error("Cannot open file for writing");
for (const auto& student : students) {
out << student.getId() << ","
<< student.getName() << ","
<< student.getAge() << ","
<< student.getGpa() << "\n";
}
}
void StudentManager::loadFromFile(const string& filename) {
ifstream in(filename);
if (!in) throw runtime_error("Cannot open file for reading");
students.clear();
string line;
while (getline(in, line)) {
stringstream ss(line);
string id, name, ageStr, gpaStr;
getline(ss, id, ',');
getline(ss, name, ',');
getline(ss, ageStr, ',');
getline(ss, gpaStr, ',');
try {
int age = stoi(ageStr);
double gpa = stod(gpaStr);
students.emplace_back(id, name, age, gpa);
} catch (...) {
cerr << "Error parsing line: " << line << endl;
}
}
}
7.4 用户界面与主程序
控制台界面实现:
cpp复制void displayMenu() {
cout << "\nStudent Management System\n"
<< "1. Add Student\n"
<< "2. Remove Student\n"
<< "3. Find Student\n"
<< "4. Display All Students\n"
<< "5. Filter by GPA\n"
<< "6. Save to File\n"
<< "7. Load from File\n"
<< "0. Exit\n"
<< "Enter your choice: ";
}
int main() {
StudentManager manager;
int choice;
do {
displayMenu();
cin >> choice;
cin.ignore(); // 清除换行符
try {
switch (choice) {
case 1: {
string id, name;
int age;
double gpa;
cout << "Enter student ID: ";
getline(cin, id);
cout << "Enter name: ";
getline(cin, name);
cout << "Enter age: ";
cin >> age;
cout << "Enter GPA: ";
cin >> gpa;
cin.ignore();
manager.addStudent(Student(id, name, age, gpa));
cout << "Student added successfully\n";
break;
}
case 2: {
string id;
cout << "Enter student ID to remove: ";
getline(cin, id);
if (manager.removeStudent(id)) {
cout << "Student removed\n";
} else {
cout << "Student not found\n";
}
break;
}
case 3: {
string id;
cout << "Enter student ID to find: ";
getline(cin, id);
auto student = manager.findStudent(id);
if (student) {
student->display();
} else {
cout << "Student not found\n";
}
break;
}
case 4:
manager.displayAll();
break;
case 5: {
double minGpa;
cout << "Enter minimum GPA: ";
cin >> minGpa;
cin.ignore();
auto topStudents = manager.filterByGpa(minGpa);
cout << "\nStudents with GPA >= " << minGpa << ":\n";
for (const auto& s : topStudents) {
s.display();
}
break;
}
case 6: {
string filename;
cout << "Enter filename to save: ";
getline(cin, filename);
manager.saveToFile(filename);
cout << "Data saved to " << filename << endl;
break;
}
case 7: {
string filename;
cout << "Enter filename to load: ";
getline(cin, filename);
manager.loadFromFile(filename);
cout << "Data loaded from " << filename << endl;
break;
}
case 0:
cout << "Exiting...\n";
break;
default:
cout << "Invalid choice\n";
}
} catch (const exception& e) {
cerr << "Error: " << e.what() << endl;
}
} while (choice != 0);
return 0;
}
8. C++工程实践进阶
8.1 异常安全与错误处理
健壮的C++程序需要妥善处理各种异常情况:
异常安全保证级别:
- 基本保证:程序保持有效状态(无资源泄漏)
- 强保证:操作要么完全成功,要么不影响程序状态
- 不抛出保证:操作保证不会抛出异常
实现强保证的示例:
cpp复制class Transaction {
vector<string> logs;
FILE* file = nullptr;
public:
void addLog(const string& message) {
logs.push_back(message);
}
void openFile(const string& filename) {
FILE* newFile = fopen(filename.c_str(), "w");
if (!newFile) throw runtime_error("Failed to open file");
// 先成功获取资源再修改状态
if (file) fclose(file);
file = newFile;
}
void commit() {
// 创建临时副本实现强保证
auto logsCopy = logs;
FILE* fileCopy = file;
try {
for (const auto& log : logsCopy) {
if (fputs((log + "\n").c_str(), fileCopy) == EOF) {
throw runtime_error("Write failed");
}
}
if (fflush(fileCopy) == EOF) {
throw runtime_error("Flush failed");
}
// 所有操作成功后才修改状态
logs.clear();
} catch (...) {
// 失败时保持原状态
logs = move(logsCopy);
throw;
}
}
~Transaction() {
if (file) fclose(file);
}
};
8.2 性能优化技巧
C++性能优化的关键策略:
1. 避免不必要的拷贝:
cpp复制// 不佳的实现
vector<string> processNames(vector<string> names) {
// 参数传递产生拷贝
sort(names.begin(), names.end());
return names; // 返回时再次拷贝
}
// 优化版本
void processNames(vector<string>& names) {
// 通过引用修改
sort(names.begin(), names.end());
}
// 或者使用移动语义
vector<string> processNames(vector<string>&& names) {
sort(names.begin(), names.end());
return move(names); // 移动而非拷贝
}
2. 预分配内存:
cpp复制vector<Data> processItems(const vector<Input>& inputs) {
vector<Data> results;
results.reserve(inputs.size()); // 避免多次重分配
for (const auto& input : inputs) {
results.push_back(process(input));
}
return results;
}
3. 使用高效算法:
cpp复制// 查找满足条件的第一个元素
auto it = find_if(begin, end, predicate); // O(n)
// 在有序范围内查找
auto it = lower_bound(begin, end, value); // O(log n)
// 移除重复元素(先排序)
sort(begin, end);
auto newEnd = unique(begin, end);
container.erase(newEnd, end);
8.3 多线程编程基础
C++11引入了标准线程支持:
基本线程创建:
cpp复制#include <thread>
#include <mutex>
mutex coutMutex;
void threadFunc(int id) {
lock_guard<mutex> lock(coutMutex);
cout << "Thread " << id << " running\n";
}
int main() {
vector<thread> threads;
for (int i = 0; i < 5; ++i) {
threads.emplace_back(threadFunc, i);
}
for (auto& t : threads) {
t.join();
}
return 0;
}
异步任务与future:
cpp复制#include <future>
int compute(int x) {
// 模拟耗时计算
this_thread::sleep_for(chrono::seconds(1));
return x * x;
}
int main() {
auto future1 = async(launch::async, compute, 5);
auto future2 = async(launch::async, compute, 8);
// 可以在这里做其他工作...
int result1 = future1.get(); // 等待并获取结果
int result2 = future2.get();
cout << "Results: " << result1 << ", " << result2 << endl;
return 0;
}
原子操作:
cpp复制#include <atomic>
atomic<int> counter(0);
void increment() {
for (int i = 0; i < 1000; ++i) {
counter.fetch_add(1, memory_order_relaxed);
}
}
int main() {
thread t1(increment);
thread t2(increment);
t1.join();
t2.join();
cout << "Final counter: " << counter << endl;
return 0;
}
9. C++最佳实践与设计模式
9.1 代码组织与模块化
良好的代码组织提升可维护性:
头文件规范示例:
cpp复制// student.h
#ifndef STUDENT_H // 头文件保护
#define STUDENT_H
#include <string>
#include <vector>
class Student {
std::string id;
std::string name;
int age;
double gpa;
public:
Student(std::string id, std::string name, int age, double gpa);
// 内联简单函数
std::string getId() const { return id; }
// 声明复杂函数
void display() const;
};
// 相关非成员函数
std::vector<Student> loadStudentsFromFile(const std::string& filename);
#endif // STUDENT_H
实现文件示例:
cpp复制// student.cpp
#include "student.h"
#include <fstream>
#include <sstream>
Student::Student(std::string id, std::string name, int age, double gpa)
: id(std::move(id)), name(std::move(name)), age(age), gpa(gpa) {
// 参数验证...
}
void Student::display() const {
// 实现细节...
}
std::vector<Student> loadStudentsFromFile(const std::string& filename) {
// 实现细节...
return {};
}
9.2 常用设计模式实现
单例模式(线程安全版):
cpp复制class Logger {
private:
static mutex mtx;
static Logger* instance;
Logger() = default; // 私有构造函数
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
public:
static Logger& getInstance() {
lock_guard<mutex> lock(mtx);
if (!instance) {
instance = new Logger();
}
return *instance;
}
void log(const string& message) {
cout << "[LOG] " << message << endl;
}
};
Logger* Logger::instance = nullptr;
mutex Logger::mtx;
工厂模式示例:
cpp复制class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() = default;
static unique_ptr<Shape> create(const string& type);
};
class Circle : public Shape {
public:
void draw() override { cout << "Drawing circle" << endl; }
};
class Square : public Shape {
public:
void draw() override { cout << "Drawing square" << endl; }
};
unique_ptr<Shape> Shape::create(const string& type) {
if (type == "circle") return make_unique<Circle>();
if (type == "square") return make_unique<Square>();
throw invalid_argument("Unknown shape type");
}
观察者模式实现:
cpp复制#include <vector>
#include <algorithm>
class Observer {
public:
virtual void update(const string& message) = 0;
virtual ~Observer() = default;
};
class Subject {
vector<Observer*> observers;
public:
void attach(Observer* obs) {
observers.push_back(obs);
}
void detach(Observer* obs) {
observers.erase(remove(observers.begin(), observers.end(), obs),
observers.end());
}
void notify(const string& message) {
for (auto obs : observers) {
obs->
