1. C++开发环境搭建与基础配置
作为一名长期使用C++进行开发的程序员,我深知一个稳定高效的开发环境对生产力有多重要。今天我想分享一套经过多年实践验证的C++开发环境配置方案,特别适合刚接触C++的新手和需要重建开发环境的老手。
1.1 编译器选择与安装
在C++开发中,编译器是核心工具链的第一环。目前主流的选择有:
- GCC:GNU Compiler Collection,开源免费,跨平台支持好
- Clang:基于LLVM,错误信息更友好,编译速度较快
- MSVC:微软Visual Studio自带,Windows平台集成度高
对于初学者,我推荐从GCC开始。在Linux上安装非常简单:
bash复制# Ubuntu/Debian
sudo apt update && sudo apt install g++ build-essential
# CentOS/RHEL
sudo yum groupinstall "Development Tools"
Windows用户可以考虑安装MinGW-w64或直接使用Visual Studio Community版。安装完成后,验证版本:
bash复制g++ --version
注意:不同版本的编译器对C++标准的支持程度不同,建议至少使用GCC 9+或Clang 10+以支持C++17特性。
1.2 构建系统配置
现代C++项目很少直接使用命令行编译,而是依赖构建系统。常见选择有:
- Makefile:传统但有效,适合小型项目
- CMake:目前最主流的跨平台构建系统
- Bazel:Google开源的构建工具,适合大型项目
对于大多数项目,CMake是最佳选择。安装CMake:
bash复制# Linux
sudo apt install cmake
# macOS
brew install cmake
# Windows
choco install cmake
一个基本的CMakeLists.txt示例:
cmake复制cmake_minimum_required(VERSION 3.10)
project(MyCppProject)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(main main.cpp)
1.3 IDE与编辑器选择
虽然理论上用文本编辑器就能写C++代码,但好的IDE能极大提升效率:
- Visual Studio Code:轻量级,通过插件支持C++
- CLion:JetBrains出品,专为C++优化
- Qt Creator:适合Qt开发,也支持纯C++
我个人的配置是VSCode + C/C++插件,配置示例.vscode/settings.json:
json复制{
"C_Cpp.default.cppStandard": "c++17",
"C_Cpp.intelliSenseEngine": "Default",
"editor.formatOnSave": true,
"cmake.configureOnOpen": true
}
2. C++项目结构与代码组织
2.1 基础项目结构
一个良好的项目结构能让代码更易维护。推荐的基础结构:
code复制my_project/
├── CMakeLists.txt
├── include/
│ └── mylib.h
├── src/
│ ├── mylib.cpp
│ └── main.cpp
├── tests/
│ └── test_mylib.cpp
└── build/
关键点:
- 头文件(.h)放在include目录
- 实现文件(.cpp)放在src目录
- 测试代码单独放在tests目录
- 构建产物放在build目录
2.2 头文件设计规范
C++的头文件设计有许多注意事项:
- 防止多重包含:使用include guard
cpp复制#ifndef MYLIB_H
#define MYLIB_H
// 头文件内容
#endif
- 前向声明:能前向声明就不要包含头文件
cpp复制class OtherClass; // 前向声明
-
最小化依赖:只包含必要的头文件
-
模板实现:模板函数/类的实现通常要放在头文件中
2.3 命名空间使用
合理使用命名空间可以避免命名冲突:
cpp复制namespace myproject {
namespace utils {
class StringHelper {
// ...
};
} // namespace utils
} // namespace myproject
使用时:
cpp复制using myproject::utils::StringHelper;
// 或者
using namespace myproject::utils;
注意:避免在头文件中使用using namespace,容易造成命名空间污染。
3. 现代C++特性实践
3.1 智能指针管理资源
现代C++推荐使用智能指针而非原始指针:
cpp复制#include <memory>
void processData() {
// 独占所有权
auto ptr = std::make_unique<int>(42);
// 共享所有权
auto sharedPtr = std::make_shared<std::vector<int>>();
// 弱引用
std::weak_ptr<std::vector<int>> weakPtr = sharedPtr;
}
3.2 移动语义与完美转发
理解移动语义可以大幅提升性能:
cpp复制class BigObject {
public:
BigObject() { /* 分配大量资源 */ }
// 移动构造函数
BigObject(BigObject&& other) noexcept {
// 转移资源而非复制
}
// 移动赋值运算符
BigObject& operator=(BigObject&& other) noexcept {
if(this != &other) {
// 释放当前资源
// 转移other的资源
}
return *this;
}
};
3.3 Lambda表达式
现代C++中lambda非常强大:
cpp复制auto lambda = [capture_list](parameters) -> return_type {
// 函数体
};
// 示例
std::vector<int> nums {1, 2, 3};
std::sort(nums.begin(), nums.end(),
[](int a, int b) { return a > b; });
4. 调试与性能优化技巧
4.1 调试工具使用
GDB基本命令:
code复制g++ -g main.cpp -o main
gdb ./main
(gdb) break main
(gdb) run
(gdb) next
(gdb) print variable
(gdb) backtrace
4.2 性能分析工具
- gprof:GNU性能分析工具
code复制g++ -pg main.cpp -o main
./main
gprof main gmon.out > analysis.txt
- perf:Linux系统级性能分析
code复制perf stat ./main
perf record ./main
perf report
4.3 常见性能优化手段
- 缓存友好设计:局部性原则,顺序访问数据
- 避免不必要的拷贝:使用移动语义或引用
- 减少动态内存分配:预分配或使用对象池
- 并行化:使用std::async或OpenMP
cpp复制// OpenMP示例
#pragma omp parallel for
for(int i = 0; i < N; ++i) {
// 并行处理
}
5. 测试与持续集成
5.1 单元测试框架
Google Test安装:
bash复制git clone https://github.com/google/googletest.git
cd googletest
mkdir build && cd build
cmake .. && make
sudo make install
测试示例:
cpp复制#include <gtest/gtest.h>
TEST(MathTest, Addition) {
EXPECT_EQ(2 + 2, 4);
}
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
5.2 CMake集成测试
在CMakeLists.txt中添加:
cmake复制enable_testing()
add_subdirectory(tests)
tests/CMakeLists.txt:
cmake复制find_package(GTest REQUIRED)
add_executable(run_tests test_mylib.cpp)
target_link_libraries(run_tests GTest::GTest mylib)
add_test(NAME mylib_test COMMAND run_tests)
5.3 持续集成配置
GitHub Actions示例.yml:
yaml复制name: C++ CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install g++ cmake
- name: Build
run: |
mkdir build
cd build
cmake ..
make
- name: Run tests
run: cd build && ctest
6. 实际项目中的经验分享
6.1 多平台兼容性处理
处理平台差异的几种方式:
- 使用预处理器指令
cpp复制#ifdef __linux__
// Linux特定代码
#elif _WIN32
// Windows特定代码
#endif
- 抽象平台相关代码
cpp复制class FileSystem {
public:
virtual void open(const std::string& path) = 0;
// ...
};
// 为不同平台实现子类
- 使用跨平台库如Boost、Qt
6.2 第三方库集成
以集成Boost为例:
- 安装Boost
bash复制sudo apt install libboost-all-dev
- CMake配置
cmake复制find_package(Boost 1.70 REQUIRED COMPONENTS filesystem system)
target_link_libraries(myapp Boost::filesystem Boost::system)
- 使用示例
cpp复制#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
fs::path p("some/file.txt");
if(fs::exists(p)) {
// ...
}
6.3 内存问题排查
常见工具:
- Valgrind:检测内存泄漏
code复制valgrind --leak-check=full ./myapp
- AddressSanitizer:GCC/Clang内置
code复制g++ -fsanitize=address -g main.cpp
典型内存问题:
- 忘记释放内存
- 越界访问
- 使用已释放内存
- 内存泄漏
6.4 异常安全编程
保证异常安全的几种级别:
- 基本保证 - 不泄露资源
- 强保证 - 操作要么完成要么回滚
- 不抛保证 - 承诺不抛出异常
实现技巧:
- RAII模式管理资源
- 避免在析构函数中抛出异常
- 使用std::optional处理可能失败的操作
cpp复制std::optional<int> safeDivide(int a, int b) {
if(b == 0) return std::nullopt;
return a / b;
}
7. C++20新特性实践
7.1 概念(Concepts)
约束模板参数:
cpp复制template<typename T>
concept Numeric = std::integral<T> || std::floating_point<T>;
template<Numeric T>
T add(T a, T b) {
return a + b;
}
7.2 协程(Coroutines)
基本协程示例:
cpp复制#include <coroutine>
struct Generator {
struct promise_type {
int current_value;
Generator get_return_object() {
return Generator{std::coroutine_handle<promise_type>::from_promise(*this)};
}
std::suspend_always initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void unhandled_exception() {}
std::suspend_always yield_value(int value) {
current_value = value;
return {};
}
};
std::coroutine_handle<promise_type> coro;
explicit Generator(std::coroutine_handle<promise_type> h) : coro(h) {}
~Generator() { if(coro) coro.destroy(); }
int next() {
coro.resume();
return coro.promise().current_value;
}
};
Generator sequence() {
int i = 0;
while(true) {
co_yield i++;
}
}
7.3 范围(Ranges)
简化容器操作:
cpp复制#include <ranges>
#include <algorithm>
#include <vector>
void processNumbers() {
std::vector<int> nums{1, 2, 3, 4, 5};
auto even = nums | std::views::filter([](int n){ return n % 2 == 0; })
| std::views::transform([](int n){ return n * 2; });
for(int n : even) {
std::cout << n << " ";
}
}
8. 项目实战:构建一个简单的HTTP服务器
8.1 设计概述
我们将使用C++20构建一个简单的多线程HTTP服务器,主要功能:
- 监听指定端口
- 处理GET/POST请求
- 支持静态文件服务
- 简单的路由功能
8.2 核心实现
网络部分使用标准库
cpp复制#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
class HttpServer {
public:
HttpServer(int port) : port_(port) {}
void start() {
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in address{};
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port_);
bind(server_fd, (sockaddr*)&address, sizeof(address));
listen(server_fd, 5);
while(true) {
int client_fd = accept(server_fd, nullptr, nullptr);
std::thread(&HttpServer::handleClient, this, client_fd).detach();
}
}
private:
void handleClient(int client_fd) {
char buffer[1024] = {0};
read(client_fd, buffer, sizeof(buffer));
// 解析请求
std::string response = "HTTP/1.1 200 OK\r\n\r\nHello World";
write(client_fd, response.c_str(), response.size());
close(client_fd);
}
int port_;
};
8.3 路由增强
添加简单路由功能:
cpp复制#include <regex>
#include <unordered_map>
class Router {
public:
using Handler = std::function<std::string(const std::smatch&)>;
void addRoute(const std::string& pattern, Handler handler) {
routes_.emplace_back(std::regex(pattern), handler);
}
std::string handleRequest(const std::string& path) {
for(auto& [regex, handler] : routes_) {
std::smatch match;
if(std::regex_match(path, match, regex)) {
return handler(match);
}
}
return "HTTP/1.1 404 Not Found\r\n\r\n";
}
private:
std::vector<std::pair<std::regex, Handler>> routes_;
};
8.4 静态文件服务
添加文件服务支持:
cpp复制#include <fstream>
#include <filesystem>
std::string serveStaticFile(const std::string& path) {
namespace fs = std::filesystem;
try {
if(!fs::exists(path) || fs::is_directory(path)) {
return "HTTP/1.1 404 Not Found\r\n\r\n";
}
std::ifstream file(path, std::ios::binary);
std::string content((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
return "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Content-Length: " + std::to_string(content.size()) + "\r\n"
"\r\n" + content;
} catch(...) {
return "HTTP/1.1 500 Internal Server Error\r\n\r\n";
}
}
9. 性能优化实战分析
9.1 热点分析实例
假设我们有一个图像处理函数:
cpp复制void processImage(std::vector<uint8_t>& image, int width, int height) {
for(int y = 0; y < height; ++y) {
for(int x = 0; x < width; ++x) {
size_t index = y * width + x;
image[index] = 255 - image[index]; // 反色
}
}
}
使用perf分析:
code复制perf record -g ./image_processor
perf report
可能发现:
- 内存访问模式不佳
- 缺乏向量化优化
9.2 优化版本
cpp复制#include <immintrin.h>
void processImageOptimized(std::vector<uint8_t>& image, int width, int height) {
const __m256i mask = _mm256_set1_epi8(0xFF);
for(int y = 0; y < height; ++y) {
uint8_t* row = image.data() + y * width;
int x = 0;
// 使用AVX2处理32字节块
for(; x + 32 <= width; x += 32) {
__m256i data = _mm256_loadu_si256(
reinterpret_cast<const __m256i*>(row + x));
data = _mm256_sub_epi8(mask, data);
_mm256_storeu_si256(reinterpret_cast<__m256i*>(row + x), data);
}
// 处理剩余部分
for(; x < width; ++x) {
row[x] = 255 - row[x];
}
}
}
9.3 性能对比
测试数据:4096x4096图像
| 版本 | 耗时(ms) | 加速比 |
|---|---|---|
| 原始 | 56.2 | 1x |
| 优化 | 6.8 | 8.3x |
10. 跨语言交互实践
10.1 C++调用Python
使用Pybind11:
- 安装Pybind11
bash复制pip install pybind11
- C++代码
cpp复制#include <pybind11/embed.h>
namespace py = pybind11;
void callPython() {
py::scoped_interpreter guard{};
py::module sys = py::module::import("sys");
py::print(sys.attr("path"));
py::module math = py::module::import("math");
double result = math.attr("sqrt")(2.0).cast<double>();
}
10.2 Python调用C++
使用Pybind11创建扩展模块:
cpp复制#include <pybind11/pybind11.h>
int add(int a, int b) {
return a + b;
}
PYBIND11_MODULE(example, m) {
m.def("add", &add, "A function that adds two numbers");
}
编译:
bash复制g++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
Python中使用:
python复制import example
print(example.add(1, 2))
10.3 C++与Rust交互
使用C ABI作为桥梁:
Rust库(lib.rs):
rust复制#[no_mangle]
pub extern "C" fn rust_add(a: i32, b: i32) -> i32 {
a + b
}
编译为静态库:
toml复制[lib]
name = "mylib"
crate-type = ["staticlib"]
C++调用:
cpp复制extern "C" {
int rust_add(int a, int b);
}
int main() {
int result = rust_add(2, 3);
return 0;
}
链接时需要包含Rust标准库。
11. 大型项目管理经验
11.1 模块化设计
推荐的项目组织结构:
code复制project/
├── core/ # 核心模块
│ ├── include/
│ ├── src/
│ └── CMakeLists.txt
├── network/ # 网络模块
│ ├── include/
│ ├── src/
│ └── CMakeLists.txt
├── third_party/ # 第三方库
│ └── CMakeLists.txt
├── apps/ # 应用程序
│ └── CMakeLists.txt
└── CMakeLists.txt # 根项目配置
根CMakeLists.txt示例:
cmake复制cmake_minimum_required(VERSION 3.12)
project(MyBigProject)
# 设置子目录
add_subdirectory(third_party)
add_subdirectory(core)
add_subdirectory(network)
add_subdirectory(apps)
11.2 依赖管理
现代C++项目推荐使用包管理器:
- vcpkg (微软)
bash复制vcpkg install boost fmt
CMake集成:
cmake复制find_package(Boost REQUIRED)
find_package(fmt REQUIRED)
- Conan
bash复制conan install .
CMake集成:
cmake复制include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
11.3 代码质量工具
- clang-format:代码格式化
.clang-format示例:
code复制BasedOnStyle: Google
IndentWidth: 4
- clang-tidy:静态分析
bash复制clang-tidy --checks=* main.cpp --
- cppcheck:代码检查
bash复制cppcheck --enable=all --inconclusive --std=c++17 src/
12. 嵌入式C++开发要点
12.1 资源受限环境编程
嵌入式开发特殊考虑:
- 避免动态内存分配
- 谨慎使用异常
- 注意中断上下文限制
- 考虑内存对齐
示例:固定大小内存池
cpp复制template<typename T, size_t N>
class MemoryPool {
public:
T* allocate() {
for(size_t i = 0; i < N; ++i) {
if(!used[i]) {
used[i] = true;
return &pool[i];
}
}
return nullptr;
}
void deallocate(T* ptr) {
size_t index = ptr - pool;
if(index < N) {
used[index] = false;
}
}
private:
T pool[N];
bool used[N] = {false};
};
12.2 寄存器操作
嵌入式设备寄存器访问:
cpp复制class GPIO {
public:
enum class PinState { Low, High };
void setPin(int pin, PinState state) {
volatile uint32_t* reg = reinterpret_cast<uint32_t*>(0x40020000);
if(state == PinState::High) {
*reg |= (1 << pin);
} else {
*reg &= ~(1 << pin);
}
}
};
12.3 实时性保证
确保实时性的技巧:
- 避免系统调用
- 禁用中断关键区域
- 使用原子操作
- 优先级继承
cpp复制#include <atomic>
class RTBuffer {
public:
void write(int value) {
while(flag_.test_and_set(std::memory_order_acquire)) {
// 自旋等待
}
data_ = value;
flag_.clear(std::memory_order_release);
}
private:
std::atomic_flag flag_ = ATOMIC_FLAG_INIT;
int data_;
};
13. GUI开发实践
13.1 Qt基础应用
简单Qt窗口示例:
cpp复制#include <QApplication>
#include <QLabel>
int main(int argc, char** argv) {
QApplication app(argc, argv);
QLabel label("Hello Qt!");
label.resize(200, 100);
label.show();
return app.exec();
}
CMake配置:
cmake复制find_package(Qt6 REQUIRED COMPONENTS Widgets)
target_link_libraries(myapp Qt6::Widgets)
13.2 信号与槽机制
Qt的核心特性:
cpp复制#include <QPushButton>
#include <QMessageBox>
class MyWindow : public QWidget {
Q_OBJECT
public:
MyWindow() {
QPushButton* btn = new QPushButton("Click me", this);
connect(btn, &QPushButton::clicked,
this, &MyWindow::showMessage);
}
private slots:
void showMessage() {
QMessageBox::information(this, "Title", "Button clicked!");
}
};
13.3 自定义控件
创建自定义按钮:
cpp复制class ColorButton : public QPushButton {
public:
ColorButton(QWidget* parent = nullptr)
: QPushButton(parent)
{
setStyleSheet("background-color: red");
}
protected:
void mousePressEvent(QMouseEvent* e) override {
setStyleSheet("background-color: green");
QPushButton::mousePressEvent(e);
}
void mouseReleaseEvent(QMouseEvent* e) override {
setStyleSheet("background-color: red");
QPushButton::mouseReleaseEvent(e);
}
};
14. 并发编程深入
14.1 线程管理
现代C++线程API:
cpp复制#include <thread>
#include <vector>
void worker(int id) {
std::cout << "Thread " << id << " working\n";
}
void runThreads() {
std::vector<std::thread> threads;
for(int i = 0; i < 4; ++i) {
threads.emplace_back(worker, i);
}
for(auto& t : threads) {
t.join();
}
}
14.2 原子操作
无锁编程基础:
cpp复制#include <atomic>
class Counter {
public:
void increment() {
value_.fetch_add(1, std::memory_order_relaxed);
}
int get() const {
return value_.load(std::memory_order_acquire);
}
private:
std::atomic<int> value_{0};
};
14.3 线程池实现
简单线程池示例:
cpp复制#include <queue>
#include <functional>
#include <condition_variable>
class ThreadPool {
public:
ThreadPool(size_t threads) : stop(false) {
for(size_t i = 0; i < threads; ++i) {
workers.emplace_back([this] {
while(true) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(queue_mutex);
condition.wait(lock, [this] {
return stop || !tasks.empty();
});
if(stop && tasks.empty()) return;
task = std::move(tasks.front());
tasks.pop();
}
task();
}
});
}
}
template<class F>
void enqueue(F&& f) {
{
std::unique_lock<std::mutex> lock(queue_mutex);
tasks.emplace(std::forward<F>(f));
}
condition.notify_one();
}
~ThreadPool() {
{
std::unique_lock<std::mutex> lock(queue_mutex);
stop = true;
}
condition.notify_all();
for(std::thread &worker : workers) {
worker.join();
}
}
private:
std::vector<std::thread> workers;
std::queue<std::function<void()>> tasks;
std::mutex queue_mutex;
std::condition_variable condition;
bool stop;
};
15. 模板元编程进阶
15.1 SFINAE技巧
类型检查示例:
cpp复制template<typename T>
auto print(T value) -> decltype(std::cout << value, void()) {
std::cout << value;
}
template<typename T>
void print(...) {
static_assert(false, "Type not printable");
}
15.2 编译时计算
constexpr函数:
cpp复制constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
static_assert(factorial(5) == 120, "Factorial error");
15.3 模板特化
全特化与偏特化:
cpp复制template<typename T>
struct IsPointer {
static constexpr bool value = false;
};
template<typename T>
struct IsPointer<T*> {
static constexpr bool value = true;
};
template<typename T>
constexpr bool is_pointer_v = IsPointer<T>::value;
16. 标准库深入使用
16.1 容器选择指南
各容器特点对比:
| 容器 | 插入 | 删除 | 查找 | 内存 | 适用场景 |
|---|---|---|---|---|---|
| vector | O(1) | O(n) | O(1) | 连续 | 随机访问多 |
| deque | O(1) | O(n) | O(1) | 分块 | 头尾操作多 |
| list | O(1) | O(1) | O(n) | 分散 | 频繁插入删除 |
| map | O(log n) | O(log n) | O(log n) | 分散 | 有序键值对 |
| unordered_map | O(1) | O(1) | O(1) | 分散 | 快速查找 |
16.2 算法应用示例
常用算法实践:
cpp复制#include <algorithm>
#include <numeric>
void processData() {
std::vector<int> nums{3, 1, 4, 1, 5, 9};
// 排序
std::sort(nums.begin(), nums.end());
// 查找
auto it = std::find(nums.begin(), nums.end(), 4);
// 累加
int sum = std::accumulate(nums.begin(), nums.end(), 0);
// 变换
std::transform(nums.begin(), nums.end(), nums.begin(),
[](int n) { return n * 2; });
}
16.3 自定义分配器
实现简单内存池分配器:
cpp复制template<typename T>
class PoolAllocator {
public:
using value_type = T;
PoolAllocator() = default;
template<class U>
PoolAllocator(const PoolAllocator<U>&) {}
T* allocate(size_t n) {
if(n != 1) throw std::bad_alloc();
return static_cast<T*>(pool_.allocate());
}
void deallocate(T* p, size_t n) {
pool_.deallocate(p);
}
private:
MemoryPool<T, 1000> pool_;
};
17. 设计模式实践
17.1 工厂模式
对象创建封装:
cpp复制class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() = default;
static std::unique_ptr<Shape> create(const std::string& type);
};
class Circle : public Shape {
public:
void draw() override { /* 画圆 */ }
};
class Square : public Shape {
public:
void draw() override { /* 画方 */ }
};
std::unique_ptr<Shape> Shape::create(const std::string& type) {
if(type == "circle") return std::make_unique<Circle>();
if(type == "square") return std::make_unique<Square>();
return nullptr;
}
17.2 观察者模式
事件通知系统:
cpp复制#include <vector>
#include <functional>
class Observer {
public:
virtual void update(int value) = 0;
};
class Subject {
public:
void attach(Observer* obs) {
observers_.push_back(obs);
}
void notify(int value) {
for(auto obs : observers_) {
obs->update(value);
}
}
private:
std::vector<Observer*> observers_;
};
17.3 策略模式
算法替换:
cpp复制class SortStrategy {
public:
virtual void sort(std::vector<int>& data) = 0;
};
class QuickSort : public SortStrategy {
public:
void sort(std::vector<int>& data) override {
std::sort(data.begin(), data.end());
}
};
class Context {
public:
void setStrategy(std::unique_ptr<SortStrategy> strategy) {
strategy_ = std::move(strategy);
}
void execute(std::vector<int>& data) {
strategy_->sort(data);
}
private:
std::unique_ptr<SortStrategy> strategy_;
};
18. 代码生成与反射
18.1 宏元编程
X宏技术示例:
cpp复制#define COLOR_TABLE \
X(Red, 0xFF0000) \
X(Green, 0x00FF00) \
X(Blue, 0x0000FF)
enum class Color {
#define X(name, value) name,
COLOR_TABLE
#undef X
};
constexpr int getColorValue(Color c) {
switch(c) {
#define X(name, value) case Color::name: return value;
COLOR_TABLE
#undef X
}
return 0;
}
18.2 运行时反射
简单反射系统:
cpp复制class TypeInfo {
public:
template<typename T>
static TypeInfo* get() {
static TypeInfo instance(typeid(T).name());
return &instance;
}
const char* name() const { return name_; }
private:
explicit TypeInfo(const char* name) : name_(name) {}
const char* name_;
};
template<typename T>
TypeInfo* type_of() {
return TypeInfo::get<T>();
}
18.3 代码生成工具
使用Clang LibTooling:
cpp复制class MyASTVisitor : public clang::RecursiveASTVisitor<MyASTVisitor> {
public:
bool VisitFunctionDecl(clang::FunctionDecl* func) {
llvm::outs() << "Found function: "
<< func->getNameAsString() << "\n";
return true;
}
};
class MyASTConsumer : public clang::ASTConsumer {
public:
void HandleTranslationUnit(clang::ASTContext& ctx) override {
visitor.TraverseDecl(ctx.getTranslationUnitDecl());
}
private:
MyASTVisitor visitor;
};
19. 安全编程实践
19.1 缓冲区安全
安全字符串处理:
cpp复制void safeCopy(char* dest, const char* src, size_t destSize) {
if(destSize == 0) return;
size_t i = 0;
while(i < destSize - 1 && src[i] != '\0') {
dest[i] = src[i];
++i;
}
dest[i] = '\0';
}
19.2 密码学基础
使用OpenSSL示例:
cpp复制#include <openssl/evp.h>
std::vector<unsigned char> sha256(const std::string& data) {
EVP_MD_CTX* ctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr);
EVP_DigestUpdate(ctx, data.data(), data.size());
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int length;
EVP_DigestFinal_ex(ctx, hash, &length);
EVP_MD_CTX_free(ctx);
return std::vector<unsigned char>(hash, hash + length);
}
19.3 安全随机数
正确生成随机数:
code复制