1. C++概述:从历史到现代编程实践
C++作为一门经久不衰的编程语言,其发展历程本身就是一部计算机编程史的缩影。1979年,Bjarne Stroustrup在贝尔实验室开始开发"C with Classes",这标志着C++的雏形诞生。1983年正式命名为C++,这个名称中的"++"象征着对C语言的超越和扩展。
提示:现代C++通常指C++11及之后的版本,它引入了许多革命性特性,如自动类型推导、lambda表达式等。
1.1 C++的核心特性解析
C++的独特之处在于它的多范式支持:
- 面向过程编程:保留了C语言的特性,适合底层系统开发
- 面向对象编程:通过类、继承、多态等特性构建复杂系统
- 泛型编程:模板机制提供了强大的代码复用能力
- 函数式编程:C++11引入的lambda表达式等特性支持函数式风格
cpp复制// 多范式示例
#include <iostream>
#include <vector>
#include <algorithm>
// 面向过程
void print(int x) { std::cout << x << " "; }
// 面向对象
class Printer {
public:
void operator()(int x) { std::cout << x << " "; }
};
// 函数式+泛型
template <typename Func>
void process(const std::vector<int>& vec, Func f) {
std::for_each(vec.begin(), vec.end(), f);
}
int main() {
std::vector<int> nums = {1, 2, 3, 4, 5};
// 三种调用方式
process(nums, print); // 函数指针
process(nums, Printer()); // 函数对象
process(nums, [](int x) { // lambda表达式
std::cout << x << " ";
});
return 0;
}
1.2 C++的应用领域深度剖析
系统级开发
操作系统内核、设备驱动等底层开发是C++的传统强项。Linux内核中约有15%的代码是C++,Windows内核也有大量C++组件。这些领域看重的是:
- 直接内存访问能力
- 高效的运行时性能
- 精细的资源控制
游戏开发
现代游戏引擎如Unreal Engine几乎完全用C++编写。游戏开发特别依赖:
- 实时性能(60FPS及以上)
- 高效的图形渲染
- 复杂物理模拟
高频交易系统
金融领域对延迟极其敏感,C++能够提供:
- 纳秒级响应时间
- 确定性的内存管理
- 与硬件直接交互的能力
嵌入式系统
资源受限环境下,C++的优势在于:
- 可预测的内存占用
- 直接寄存器操作
- 实时性保证
2. 第一个C++程序:从Hello World到工程实践
2.1 现代C++的Hello World
传统的Hello World程序虽然简单,但现代C++实践中我们需要注意更多细节:
cpp复制#include <iostream>
int main(int argc, char* argv[]) {
// 检查参数数量
if (argc > 1) {
std::cout << "Hello, " << argv[1] << "!\n";
} else {
std::cout << "Hello, World!\n";
}
// 返回状态码
return EXIT_SUCCESS; // 比直接返回0更具可读性
}
2.2 编译器的选择与使用技巧
GCC/Clang编译选项详解
bash复制# 基本编译
g++ -std=c++17 -Wall -Wextra -pedantic -o program main.cpp
# 调试版本
g++ -g -O0 -DDEBUG -o program_debug main.cpp
# 发布版本
g++ -O3 -march=native -DNDEBUG -o program_release main.cpp
现代构建工具
- CMake:跨平台构建系统
cmake复制cmake_minimum_required(VERSION 3.10)
project(HelloWorld)
add_executable(hello main.cpp)
set_target_properties(hello PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
)
2.3 工程化实践要点
- 头文件保护:防止重复包含
cpp复制#ifndef MY_HEADER_H
#define MY_HEADER_H
// 头文件内容
#endif
- 命名空间使用:避免污染全局空间
cpp复制namespace myproject {
namespace utils {
// 工具函数
} // namespace utils
} // namespace myproject
- 异常处理基础
cpp复制try {
// 可能抛出异常的代码
throw std::runtime_error("Something went wrong");
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
3. C++与C的关键差异解析
3.1 类型系统增强
引用与指针的区别
cpp复制int x = 10;
int* ptr = &x; // 指针
int& ref = x; // 引用
*ptr = 20; // 通过指针修改
ref = 30; // 通过引用修改
// 关键区别:
// 1. 引用必须初始化且不能改变绑定
// 2. 引用使用更直观,不需要解引用
// 3. 指针可以指向nullptr,引用不能
类型安全增强
cpp复制// C风格转换(不推荐)
double d = 3.14;
int i = (int)d;
// C++风格转换
int j = static_cast<int>(d); // 静态类型检查
const int* cp = &i;
int* p = const_cast<int*>(cp); // 移除const属性
3.2 函数特性对比
函数重载
cpp复制void print(int x) { std::cout << "int: " << x << std::endl; }
void print(double x) { std::cout << "double: " << x << std::endl; }
void print(const std::string& s) { std::cout << "string: " << s << std::endl; }
// 调用时根据参数类型自动选择
print(10); // 调用int版本
print(3.14); // 调用double版本
print("hello"); // 调用string版本
默认参数
cpp复制void log(const std::string& message,
int level = 1,
const std::string& prefix = "[INFO]") {
std::cout << prefix << "(" << level << "): " << message << std::endl;
}
// 调用方式
log("Starting up"); // 使用全部默认参数
log("Warning", 2); // 覆盖第一个默认参数
log("Error", 3, "[CRITICAL]"); // 覆盖所有默认参数
4. 数据类型与变量:从基础到高级用法
4.1 现代C++类型系统
类型推导(C++11起)
cpp复制auto x = 42; // int
auto y = 3.14; // double
auto z = "hello"; // const char*
auto& ref = x; // int&
const auto& cref = y; // const double&
// decltype获取表达式类型
decltype(x) another_x = 10;
固定宽度整数类型(C++11)
cpp复制#include <cstdint>
int8_t small; // 精确8位有符号整数
uint16_t medium; // 精确16位无符号整数
int32_t large; // 精确32位有符号整数
int64_t huge; // 精确64位有符号整数
4.2 变量生命周期与存储类别
存储类别比较
cpp复制int global_var; // 静态存储期,外部链接
void func() {
static int count = 0; // 静态存储期,内部链接
int local_var; // 自动存储期
register int fast_var; // 建议寄存器存储(已过时)
// 动态存储期
int* dynamic_var = new int(42);
delete dynamic_var;
}
初始化方式演进
cpp复制// C风格初始化
int x = 42;
// 构造函数初始化
int y(42);
// C++11统一初始化
int z{42}; // 禁止窄化转换
int array[]{1, 2, 3};
// C++17结构化绑定
auto [a, b] = std::make_pair(1, "two");
5. 运算符详解:从基础到高级技巧
5.1 运算符重载实战
cpp复制class Vector {
public:
float x, y;
Vector(float x, float y) : x(x), y(y) {}
// 重载+运算符
Vector operator+(const Vector& other) const {
return Vector(x + other.x, y + other.y);
}
// 重载<<运算符(友元函数)
friend std::ostream& operator<<(std::ostream& os, const Vector& v) {
return os << "(" << v.x << ", " << v.y << ")";
}
};
int main() {
Vector v1(1, 2), v2(3, 4);
Vector v3 = v1 + v2; // 使用重载的+运算符
std::cout << v3 << std::endl; // 输出: (4, 6)
return 0;
}
5.2 移动语义与右值引用(C++11)
cpp复制class String {
char* data;
public:
// 移动构造函数
String(String&& other) noexcept
: data(other.data) {
other.data = nullptr;
}
// 移动赋值运算符
String& operator=(String&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
other.data = nullptr;
}
return *this;
}
~String() { delete[] data; }
};
String createString() {
String s;
// ... 初始化s
return s; // 触发移动语义
}
6. 控制结构:从基础语法到模式应用
6.1 现代循环技术
基于范围的for循环(C++11)
cpp复制std::vector<int> nums = {1, 2, 3, 4, 5};
// 只读访问
for (int num : nums) {
std::cout << num << " ";
}
// 修改元素
for (int& num : nums) {
num *= 2;
}
// 使用auto简化
for (auto& num : nums) {
std::cout << num << " ";
}
结构化绑定(C++17)
cpp复制std::map<std::string, int> scores = {{"Alice", 90}, {"Bob", 85}};
for (const auto& [name, score] : scores) {
std::cout << name << ": " << score << std::endl;
}
6.2 条件语句高级用法
constexpr if(C++17)
cpp复制template <typename T>
auto get_value(T t) {
if constexpr (std::is_pointer_v<T>) {
return *t; // 解引用指针类型
} else {
return t; // 直接返回值
}
}
初始化语句的if/switch(C++17)
cpp复制if (auto it = map.find(key); it != map.end()) {
// 使用it
} else {
// 处理未找到情况
}
switch (int code = get_code(); code) {
case 200: // ...
case 404: // ...
// ...
}
7. 函数深度解析:从参数传递到lambda表达式
7.1 参数传递机制对比
cpp复制void by_value(std::string s) {} // 拷贝构造
void by_ref(std::string& s) {} // 非常量引用
void by_const_ref(const std::string& s) {} // 常量引用
void by_rvalue_ref(std::string&& s) {} // 右值引用
std::string str = "hello";
by_value(str); // 拷贝构造新对象
by_ref(str); // 直接操作原对象
by_const_ref(str); // 只读访问原对象
by_rvalue_ref(std::move(str)); // 移动语义
7.2 Lambda表达式全解析(C++11起)
cpp复制// 基本形式
auto basic = [] { std::cout << "Hello"; };
// 带参数和返回类型
auto add = [](int a, int b) -> int { return a + b; };
// 捕获列表详解
int x = 10, y = 20;
// 值捕获
auto capture_val = [x] { return x; };
// 引用捕获
auto capture_ref = [&y] { y++; };
// 混合捕获
auto mixed = [x, &y] { return x + y; };
// 初始化捕获(C++14)
auto init_capture = [z = x + y] { return z; };
// 泛型lambda(C++14)
auto generic = [](auto a, auto b) { return a + b; };
// mutable lambda
auto counter = [count = 0]() mutable { return ++count; };
8. 数组与字符串:从C风格到现代C++
8.1 std::array vs 原生数组
cpp复制#include <array>
#include <algorithm>
// C风格数组
int c_array[5] = {1, 2, 3, 4, 5};
// std::array (C++11)
std::array<int, 5> cpp_array = {1, 2, 3, 4, 5};
// 比较优势:
// 1. 知道自己的大小(cpp_array.size())
// 2. 不会退化为指针
// 3. 支持迭代器
// 4. 可以作为函数返回值
// 5. 支持STL算法
std::sort(cpp_array.begin(), cpp_array.end());
8.2 现代字符串处理
std::string_view(C++17)
cpp复制#include <string_view>
void process(std::string_view sv) {
// 不需要拷贝,只读视图
if (sv.starts_with("http")) {
// ...
}
auto substr = sv.substr(0, 5);
}
// 可以接受多种字符串类型
process("C-style string"); // C风格
process(std::string("C++ str")); // std::string
process("Literal"s.substr(0,3)); // string临时对象
字符串格式化(C++20)
cpp复制#include <format>
std::string message = std::format("Hello, {}! The answer is {}.", "World", 42);
// message = "Hello, World! The answer is 42."
9. 指针与引用:从基础到智能指针
9.1 智能指针详解(C++11起)
cpp复制#include <memory>
// 独占所有权
std::unique_ptr<Resource> up(new Resource());
// 共享所有权
std::shared_ptr<Resource> sp1 = std::make_shared<Resource>();
auto sp2 = sp1; // 引用计数增加
// 弱引用
std::weak_ptr<Resource> wp = sp1;
// 自定义删除器
std::unique_ptr<FILE, decltype(&fclose)>
file(fopen("data.txt", "r"), &fclose);
9.2 现代指针技术
观察者模式实现
cpp复制class Observer {
public:
virtual void update() = 0;
virtual ~Observer() = default;
};
class Subject {
std::vector<std::weak_ptr<Observer>> observers;
public:
void add_observer(std::weak_ptr<Observer> obs) {
observers.push_back(obs);
}
void notify() {
for (auto& weak_obs : observers) {
if (auto obs = weak_obs.lock()) {
obs->update();
}
}
}
};
10. 动态内存管理:从new/delete到现代实践
10.1 内存管理最佳实践
- RAII原则:资源获取即初始化
cpp复制class FileHandle {
FILE* file;
public:
explicit FileHandle(const char* filename)
: file(fopen(filename, "r")) {
if (!file) throw std::runtime_error("File open failed");
}
~FileHandle() { if (file) fclose(file); }
// 禁用拷贝
FileHandle(const FileHandle&) = delete;
FileHandle& operator=(const FileHandle&) = delete;
// 允许移动
FileHandle(FileHandle&& other) noexcept : file(other.file) {
other.file = nullptr;
}
};
- 自定义内存管理
cpp复制class MemoryPool {
struct Block { /* ... */ };
std::vector<Block*> free_blocks;
public:
void* allocate(size_t size) {
if (free_blocks.empty()) {
return ::operator new(size);
}
// 从池中分配
}
void deallocate(void* p, size_t size) {
// 返回池中
}
};
template <typename T>
struct PoolAllocator {
// 实现allocator接口
};
11. 综合案例:构建一个简单的学生管理系统
cpp复制#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
class Student {
std::string name;
int id;
double gpa;
public:
Student(std::string n, int i, double g)
: name(std::move(n)), id(i), gpa(g) {}
// 访问器
const std::string& get_name() const { return name; }
int get_id() const { return id; }
double get_gpa() const { return gpa; }
// 输出运算符重载
friend std::ostream& operator<<(std::ostream& os, const Student& s) {
return os << s.id << ": " << s.name << " (GPA: " << s.gpa << ")";
}
};
class StudentDatabase {
std::vector<std::unique_ptr<Student>> students;
public:
void add_student(std::string name, int id, double gpa) {
students.push_back(
std::make_unique<Student>(std::move(name), id, gpa)
);
}
void remove_student(int id) {
students.erase(
std::remove_if(students.begin(), students.end(),
[id](const auto& s) { return s->get_id() == id; }),
students.end()
);
}
void print_all() const {
for (const auto& s : students) {
std::cout << *s << std::endl;
}
}
const Student* find_by_id(int id) const {
auto it = std::find_if(students.begin(), students.end(),
[id](const auto& s) { return s->get_id() == id; });
return it != students.end() ? it->get() : nullptr;
}
};
int main() {
StudentDatabase db;
db.add_student("Alice", 1001, 3.8);
db.add_student("Bob", 1002, 3.5);
db.add_student("Charlie", 1003, 3.2);
std::cout << "All students:\n";
db.print_all();
std::cout << "\nRemoving Bob...\n";
db.remove_student(1002);
std::cout << "\nAfter removal:\n";
db.print_all();
if (auto s = db.find_by_id(1001)) {
std::cout << "\nFound: " << *s << std::endl;
}
return 0;
}
12. 常见问题与性能优化技巧
12.1 内存问题排查
- 内存泄漏检测
cpp复制#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
int main() {
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
// ... 你的代码
return 0;
}
- 性能分析技巧
- 使用
<chrono>测量代码段执行时间
cpp复制auto start = std::chrono::high_resolution_clock::now();
// 要测量的代码
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << "Time taken: " << duration.count() << " microseconds\n";
12.2 现代C++最佳实践
- 优先使用标准库算法
cpp复制std::vector<int> nums = {5, 3, 1, 4, 2};
// 传统循环
for (size_t i = 0; i < nums.size(); ++i) {
nums[i] *= 2;
}
// 现代风格
std::transform(nums.begin(), nums.end(), nums.begin(),
[](int x) { return x * 2; });
- 异常安全编程
cpp复制class ResourceGuard {
Resource* res;
public:
explicit ResourceGuard(Resource* r) : res(r) {}
~ResourceGuard() { if (res) res->release(); }
// 禁用拷贝
ResourceGuard(const ResourceGuard&) = delete;
ResourceGuard& operator=(const ResourceGuard&) = delete;
};
void process_resource() {
Resource* r = acquire_resource();
ResourceGuard guard(r); // 确保资源释放
// 使用资源
// 即使抛出异常,资源也会被正确释放
}
- 移动语义优化
cpp复制class Buffer {
size_t size;
char* data;
public:
// 移动构造函数
Buffer(Buffer&& other) noexcept
: size(other.size), data(other.data) {
other.size = 0;
other.data = nullptr;
}
// 移动赋值运算符
Buffer& operator=(Buffer&& other) noexcept {
if (this != &other) {
delete[] data;
size = other.size;
data = other.data;
other.size = 0;
other.data = nullptr;
}
return *this;
}
};
13. C++20/23新特性前瞻
13.1 C++20核心特性
- 概念(Concepts)
cpp复制template <typename T>
concept Addable = requires(T a, T b) {
{ a + b } -> std::same_as<T>;
};
template <Addable T>
T sum(T a, T b) { return a + b; }
- 协程(Coroutines)
cpp复制#include <coroutine>
generator<int> range(int start, int end) {
for (int i = start; i < end; ++i)
co_yield i;
}
void use_coroutine() {
for (int i : range(1, 10)) {
std::cout << i << " ";
}
}
13.2 C++23值得期待的特性
- std::expected错误处理
cpp复制std::expected<int, std::string> parse_number(std::string_view s) {
try {
return std::stoi(std::string(s));
} catch (...) {
return std::unexpected("parse error");
}
}
void handle_result() {
if (auto num = parse_number("123")) {
use(*num);
} else {
log_error(num.error());
}
}
- 多维视图(mdspan)
cpp复制#include <mdspan>
void process_matrix() {
std::vector<double> data(100); // 10x10矩阵
std::mdspan mat(data.data(), 10, 10);
for (int i = 0; i < mat.extent(0); ++i) {
for (int j = 0; j < mat.extent(1); ++j) {
mat[i, j] = i * j;
}
}
}
14. 学习路线与资源推荐
14.1 系统学习路径
-
基础阶段(1-3个月)
- 《C++ Primer》第5版
- 掌握基本语法和标准库使用
- 理解面向对象编程概念
-
进阶阶段(3-6个月)
- 《Effective C++》系列
- 学习模板和泛型编程
- 理解内存模型和并发基础
-
高级阶段(6-12个月)
- 《C++ Templates: The Complete Guide》
- 研究标准库实现原理
- 掌握现代C++特性(C++11/14/17/20)
14.2 实用工具链
-
编译器
- GCC/G++:最新稳定版
- Clang/LLVM:优秀的错误提示
- MSVC:Windows平台开发
-
构建系统
- CMake:现代跨平台构建
- Bazel:大规模项目构建
- Conan:C++包管理器
-
调试工具
- GDB/LLDB:命令行调试器
- Valgrind:内存检查工具
- AddressSanitizer:内存错误检测
-
IDE选择
- Visual Studio:Windows平台最强
- CLion:跨平台专业C++ IDE
- VS Code + C++插件:轻量级选择
15. 面试常见问题解析
15.1 语言特性相关问题
- const关键字的作用
cpp复制const int a = 10; // 常量整数
const int* p1 = &a; // 指向常量的指针
int* const p2 = &b; // 常量指针
const int* const p3 = &a; // 指向常量的常量指针
// 成员函数中的const
class MyClass {
void func() const; // 不修改对象状态的成员函数
};
- 虚函数实现原理
- 虚函数表(vtable)机制
- 运行时多态的实现方式
- 虚函数调用开销分析
15.2 算法与数据结构实现
- 智能指针实现
cpp复制template <typename T>
class SimpleUniquePtr {
T* ptr;
public:
explicit SimpleUniquePtr(T* p = nullptr) : ptr(p) {}
~SimpleUniquePtr() { delete ptr; }
// 禁用拷贝
SimpleUniquePtr(const SimpleUniquePtr&) = delete;
SimpleUniquePtr& operator=(const SimpleUniquePtr&) = delete;
// 允许移动
SimpleUniquePtr(SimpleUniquePtr&& other) noexcept : ptr(other.ptr) {
other.ptr = nullptr;
}
T& operator*() const { return *ptr; }
T* operator->() const { return ptr; }
};
- 常用容器实现
cpp复制template <typename T>
class SimpleVector {
T* data;
size_t capacity;
size_t size;
void resize(size_t new_capacity) {
T* new_data = new T[new_capacity];
for (size_t i = 0; i < size; ++i) {
new_data[i] = std::move(data[i]);
}
delete[] data;
data = new_data;
capacity = new_capacity;
}
public:
SimpleVector() : data(nullptr), capacity(0), size(0) {}
void push_back(const T& value) {
if (size >= capacity) {
resize(capacity == 0 ? 1 : capacity * 2);
}
data[size++] = value;
}
// 其他成员函数...
};
16. 性能优化实战技巧
16.1 缓存友好设计
- 数据局部性优化
cpp复制// 不好的设计:碎片化内存访问
struct BadNode {
int value;
BadNode* next;
BadNode* prev;
};
// 好的设计:连续内存存储
class NodePool {
std::vector<Node> nodes;
std::vector<size_t> free_list;
public:
Node* allocate() {
if (free_list.empty()) {
nodes.emplace_back();
return &nodes.back();
}
size_t idx = free_list.back();
free_list.pop_back();
return &nodes[idx];
}
};
- 分支预测优化
cpp复制// 可能的分支预测失败
for (const auto& item : items) {
if (item.is_special()) { // 条件跳转
process_special(item);
} else {
process_normal(item);
}
}
// 优化版本:分离处理
std::vector<Item*> specials;
for (auto& item : items) {
if (item.is_special()) {
specials.push_back(&item);
}
}
// 处理普通项
for (auto& item : items) {
if (!item.is_special()) {
process_normal(item);
}
}
// 处理特殊项
for (auto* item : specials) {
process_special(*item);
}
16.2 并行计算基础
- std::async异步任务
cpp复制#include <future>
int compute_heavy_task(int x) {
// 耗时计算
return x * x;
}
void run_parallel() {
auto fut1 = std::async(std::launch::async, compute_heavy_task, 10);
auto fut2 = std::async(std::launch::async, compute_heavy_task, 20);
int result1 = fut1.get();
int result2 = fut2.get();
std::cout << "Results: " << result1 << ", " << result2 << std::endl;
}
- 原子操作与内存顺序
cpp复制#include <atomic>
std::atomic<int> counter{0};
void increment() {
for (int i = 0; i < 1000; ++i) {
counter.fetch_add(1, std::memory_order_relaxed);
}
}
void test_atomic() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "Final counter: " << counter << std::endl;
}
17. 跨平台开发注意事项
17.1 平台相关代码处理
- 条件编译
cpp复制#ifdef _WIN32
#include <windows.h>
void platform_specific() {
// Windows特有代码
}
#elif defined(__linux__)
#include <unistd.h>
void platform_specific() {
// Linux特有代码
}
#endif
- 字节序处理
cpp复制#include <cstdint>
inline uint32_t swap_endian(uint32_t val) {
return ((val << 24) & 0xff000000) |
((val << 8) & 0x00ff0000) |
((val >> 8) & 0x0000ff00) |
((val >> 24) & 0x000000ff);
}
uint32_t read_network_order(const char* buf) {
uint32_t value;
memcpy(&value, buf, sizeof(value));
// 检测本地字节序
constexpr uint32_t test = 0x01020304;
if (reinterpret_cast<const uint8_t*>(&test)[0] == 0x01) {
// 大端序,需要转换
return swap_endian(value);
}
return value;
}
17.2 跨平台构建系统
CMake跨平台配置示例
cmake复制# 检测操作系统
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
add_definitions(-DWIN32_LEAN_AND_MEAN)
list(APPEND LIBS ws2_32)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
list(APPEND LIBS pthread)
endif()
# 检测编译器
if(MSVC)
add_compile_options(/W4 /WX)
else()
add_compile_options(-Wall -Wextra -pedantic -Werror)
endif()
# 跨平台安装路径
include(GNUInstallDirs)
install(TARGETS mylib
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
18. 模板元编程入门
18.1 SFINAE与类型萃取
cpp复制#include <type_traits>
// SFINAE示例
template <typename T>
auto print(const T& value) -> decltype(std::cout << value, void()) {
std::cout << value << std::endl;
}
void print(...) {
std::cout << "[object cannot be printed]" << std::endl;
}
// 类型萃取示例
template <typename T>
void process(const T& value) {
if constexpr (std::is_integral_v<T>) {
std::cout << "Integral: " << value * 2 << std::endl;
} else if constexpr (std::is_floating_point_v<T>) {
std::cout << "Floating: " << value / 2 << std::endl;
} else {
std::cout << "Other type" << std::endl;
}
}
18.2 编译时计算
cpp复制// 编译时阶乘计算
template <unsigned N>
struct Factorial {
static constexpr unsigned value = N * Factorial<N-1>::value;
};
template <>
struct Factorial<0> {
static constexpr unsigned value = 1;
};
// C++14起可以使用constexpr函数
constexpr unsigned factorial(unsigned n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
void use_factorial() {
constexpr auto f1 = Factorial<5>::value; // 编译时计算
constexpr auto f2 = factorial(5); // 编译时计算
int x = 5;
auto f3 = factorial(x); // 运行时计算
}
19. 设计模式C++实现
19.1 工厂模式
cpp复制class Product {
public:
virtual ~Product() = default;
virtual void operation() = 0;
};
class ConcreteProductA : public Product {
public:
void operation() override {
std::cout << "Product A operation" << std::endl;
}
};
class ConcreteProductB : public Product {
public:
void operation() override {
std::cout << "Product B operation" << std::endl;
}
};
class Factory {
public:
enum class Type { A, B };
static std::unique_ptr<Product> create(Type type) {
switch