跳到主要内容
C++ 经典面试题精选:从基础语法到设计模式 | 极客日志
C++ 算法
C++ 经典面试题精选:从基础语法到设计模式 C++ 面试题涵盖基础语法、内存管理、现代特性及设计模式。内容包含 100 道高频考点,涉及面向对象、STL、智能指针、多线程及 SOLID 原则。通过实战代码示例与原理剖析,帮助开发者系统复习核心知识点,提升面试通过率。
筑梦师 发布于 2026/2/12 更新于 2026/4/25 0 浏览C++ 经典面试题精选
第一部分:C++ 基础语法
面向对象基础
1. 什么是面向对象编程?C++ 中如何体现?
面向对象编程(OOP)是一种通过对象组织代码的范式。在 C++ 中主要体现在封装、继承和多态上。
class Animal {
public :
virtual void makeSound () = 0 ;
};
class Dog : public Animal {
public :
void makeSound () override {
std::cout << "Woof!" << std::endl;
}
};
2. 类和结构的区别?
主要区别在于默认访问权限:class 默认为 private,而 struct 默认为 public。
class MyClass {
int x;
};
struct MyStruct {
int x;
};
3. 构造函数的作用和种类?
构造函数用于初始化对象。包括默认构造函数、参数化构造函数、拷贝构造函数以及 C++11 引入的移动构造函数。
class Example {
public :
Example () {}
Example (int x) : val (x) {}
Example (const Example& other) : (other.val) {}
(Example&& other) : (other.val) {}
:
val;
};
val
Example
noexcept
val
private
int
析构函数用于清理对象资源。当对象生命周期结束、使用 delete 释放动态分配对象或程序正常结束时调用。
class Resource {
public :
Resource () { data = new int [100 ]; }
~Resource () { delete [] data; }
private :
int * data;
};
拷贝构造函数用同类型对象初始化新对象。如果类包含指针成员且需要深拷贝,或者有特殊逻辑时,必须手动实现。
class String {
public :
String (const char * str) {
data = new char [strlen (str) + 1 ];
strcpy (data, str);
}
String (const String& other) {
data = new char [strlen (other.data) + 1 ];
strcpy (data, other.data);
}
~String () { delete [] data; }
private :
char * data;
};
移动构造函数(C++11)通过'窃取'资源而非拷贝来提高性能,避免深拷贝开销,特别适用于临时对象和大对象。
class Vector {
public :
Vector (Vector&& other) noexcept
: data (other.data), size (other.size), capacity (other.capacity) {
other.data = nullptr ;
other.size = other.capacity = 0 ;
}
private :
int * data;
size_t size, capacity;
};
初始化列表直接初始化类成员,效率更高(避免先默认构造再赋值)。对于 const 成员、引用成员及无默认构造函数的成员是必须的。
class Person {
public :
Person (const std::string& name, int age)
: name_ (name), age_ (age) {
}
private :
std::string name_;
int age_;
};
this 指针指向当前对象,用于区分成员变量和参数,返回当前对象的引用等。
class Student {
public :
Student& setName (const std::string& name) {
this ->name = name;
return *this ;
}
private :
std::string name;
};
访问控制与封装 9. public、private、protected 的区别?
public :类内外都可访问。
private :只有类内和友元可访问。
protected :类内、派生类、友元可访问。
class Base {
public :
int pub;
protected :
int prot;
private :
int priv;
};
class Derived : public Base {
public :
void access () {
pub = 1 ;
prot = 2 ;
}
};
友元可以访问类的私有和保护成员。友元函数是非成员函数,友元类则是另一个类的所有成员函数都可访问。
class Box {
friend void printBox (const Box& box) ;
friend class BoxPrinter ;
private :
int width, height;
};
void printBox (const Box& box) {
std::cout << box.width << "x" << box.height;
}
封装将数据和操作数据的方法绑定在一起,隐藏内部实现。这有助于数据保护、接口清晰化和易于维护。
class BankAccount {
public :
void deposit (double amount) { balance += amount; }
bool withdraw (double amount) {
if (amount <= balance) {
balance -= amount;
return true ;
}
return false ;
}
double getBalance () const { return balance; }
private :
double balance = 0.0 ;
};
承诺不修改对象状态,可以被 const 对象调用,不能修改非 mutable 成员变量,提高安全性和可读性。
class Rectangle {
public :
double getArea () const {
return width * height;
}
void setWidth (double w) { width = w; }
private :
double width, height;
};
允许在 const 成员函数中修改特定成员变量,常用于缓存、计数器等逻辑上保持 const 但需修改的场景。
class Calculator {
public :
int getResult () const {
cache_count++;
return compute ();
}
private :
mutable int cache_count = 0 ;
int compute () const { return 42 ; }
};
继承与多态 C++ 有三种继承方式:public(保持访问级别)、protected(基类 public/protected 变为 protected)、private(基类 public/protected 变为 private)。
class Base {
public : int pub;
protected : int prot;
private : int priv;
};
class PublicDerived : public Base {};
class PrivateDerived : private Base {};
虚函数实现运行时多态,允许通过基类指针调用派生类的实现。需要 virtual 关键字声明,通过虚函数表实现。
class Shape {
public :
virtual double getArea () const = 0 ;
virtual void draw () const {
std::cout << "Drawing shape" << std::endl;
}
};
class Circle : public Shape {
public :
double getArea () const override {
return 3.14 * radius * radius;
}
void draw () const override {
std::cout << "Drawing circle" << std::endl;
}
private :
double radius;
};
纯虚函数 :没有实现的虚函数,= 0 表示。
抽象类 :包含纯虚函数的类,不能实例化。
class Animal {
public :
virtual void makeSound () = 0 ;
virtual void eat () {
std::cout << "Eating" << std::endl;
}
};
class Dog : public Animal {
public :
void makeSound () override {
std::cout << "Woof!" << std::endl;
}
};
虚函数表是实现多态的机制。每个有虚函数的类都有一个虚函数表,对象中包含指向它的指针(vptr),表中存储虚函数的地址。
class Base {
public :
virtual void func1 () {}
virtual void func2 () {}
};
明确表示重写基类虚函数。编译器会检查是否真的重写了基类函数,防止拼写错误或参数不匹配,提高可读性。
class Base {
public :
virtual void process (int value) {}
};
class Derived : public Base {
public :
void process (int value) override {
}
};
阻止继承或重写。修饰类表示不能被继承,修饰虚函数表示不能被重写。
class FinalClass final {
public :
virtual void method () final {
}
};
问题包括菱形继承导致的二义性和数据冗余。解决方案是使用虚继承或明确作用域限定。
class Animal {
public :
void eat () {
std::cout << "Eating" << std::endl;
}
};
class Mammal : virtual public Animal {};
class Bird : virtual public Animal {};
class Bat : public Mammal, public Bird {
public :
void test () {
eat ();
}
};
运算符重载 不能重载的运算符包括 ., ::, sizeof, typeid, .*, ?:。必须重载为成员函数的有 =, (), [], ->。不能改变优先级和结合性。
class Complex {
public :
Complex operator +(const Complex& other) const {
return Complex (real + other.real, imag + other.imag);
}
friend Complex operator *(const Complex& c1, const Complex& c2);
private :
double real, imag;
};
前置 ++ 无参数,返回引用;后置 ++ 带 int 参数(仅用于区分),返回值。
class Counter {
public :
Counter& operator ++() {
++value;
return *this ;
}
Counter operator ++(int ) {
Counter temp = *this ;
++value;
return temp;
}
private :
int value = 0 ;
};
检查自赋值,返回当前对象的引用,正确处理资源,考虑异常安全。
class String {
public :
String& operator =(const String& other) {
if (this != &other) {
delete [] data;
data = new char [strlen (other.data) + 1 ];
strcpy (data, other.data);
}
return *this ;
}
private :
char * data;
};
通常提供 const 和非 const 两个版本,应进行边界检查,返回引用以支持修改。
class Array {
public :
int & operator [](size_t index) {
if (index >= size) throw std::out_of_range ("Index out of range" );
return data[index];
}
const int & operator [](size_t index) const {
if (index >= size) throw std::out_of_range ("Index out of range" );
return data[index];
}
private :
int * data;
size_t size;
};
使对象可以像函数一样调用,创建函数对象(functor),支持任意参数列表,常用于 STL 算法。
class Adder {
public :
int operator () (int a, int b) const {
return a + b;
}
};
class Multiplier {
private :
int factor;
public :
Multiplier (int f) : factor (f) {}
int operator () (int x) const {
return x * factor;
}
};
第二部分:C++ 核心特性
模板编程 允许编写泛型函数,支持多种数据类型。使用 template 关键字声明,类型参数用 typename 或 class。
template <typename T>
T max (T a, T b) {
return (a > b) ? a : b;
}
int i = max (3 , 7 );
double d = max (3.14 , 2.71 );
定义泛型类,支持多种数据类型。成员函数在类外定义时需要模板声明,支持非类型模板参数和特化。
template <typename T>
class Stack {
private :
std::vector<T> elements;
public :
void push (const T& elem) {
elements.push_back (elem);
}
T pop () {
if (elements.empty ()) {
throw std::out_of_range ("Stack<>::pop(): empty stack" );
}
T elem = elements.back ();
elements.pop_back ();
return elem;
}
};
Stack<int > intStack;
Stack<std::string> stringStack;
为特定类型提供定制实现。分为完全特化(所有参数指定)和部分特化(部分参数指定,仅类模板)。
template <typename T>
class Calculator {
public :
T add (T a, T b) { return a + b; }
};
template <>
class Calculator <const char *> {
public :
const char * add (const char * a, const char * b) {
char * result = new char [strlen (a) + strlen (b) + 1 ];
strcpy (result, a);
strcat (result, b);
return result;
}
};
template <typename T>
class Calculator <T*> {
public :
T add (T* a, T* b) { return *a + *b; }
};
包括类型参数(typename T)、非类型参数(int size, bool flag)和模板模板参数(template class Container)。
template <typename T, int SIZE, bool DEBUG = false >
class Buffer {
private :
T data[SIZE];
public :
void set (int index, const T& value) {
if (DEBUG) std::cout << "Setting index " << index << std::endl;
data[index] = value;
}
};
template <typename T, template <typename , typename > class Container >
class Adapter {
private :
Container<T, std::allocator<T>> container;
public :
void add (const T& item) {
container.push_back (item);
}
};
替换失败不是错误(Substitution Failure Is Not An Error)。模板参数替换失败时不会编译错误,而是寻找其他重载。常用于模板元编程和类型萃取。
template <typename T>
typename T::value_type test (typename T::iterator*) ;
template <typename >
int test (...) ;
template <typename T>
auto hasIterator (T t) -> decltype (test<T>(nullptr )) {
return true ;
}
template <typename T>
int hasIterator (...) {
return false ;
}
编译期遇到模板使用时生成具体代码。
两阶段查找:模板定义时和实例化时。
隐式实例化:使用时自动生成。
显式实例化:明确指定类型。
template <typename T>
T square (T x) {
return x * x;
}
int result1 = square (5 );
double result2 = square (3.14 );
template int square <int >(int );
优点:代码复用、类型安全、性能与手写代码相同。缺点:编译时间长、代码膨胀、调试困难、老旧编译器支持有限。
STL 容器 动态数组,连续内存,随机访问,自动扩容。访问 O(1),插入删除 O(n)。适用于频繁随机访问、尾部插入。
std::vector<int > vec;
vec.push_back (1 );
vec[0 ] = 10 ;
vec.size ();
vec.capacity ();
vec.reserve (100 );
双向链表,非连续内存,双向遍历,任意位置插入删除。访问 O(n),插入删除 O(1)。适用于频繁插入删除、不需要随机访问。
std::list<int > lst;
lst.push_front (1 );
lst.push_back (2 );
auto it = lst.begin ();
lst.insert (it, 3 );
lst.erase (it);
35. map 和 unordered_map 的区别?
特性 map unordered_map 底层结构 红黑树 哈希表 有序性 有序 无序 查找复杂度 O(log n) O(1) 平均 插入复杂度 O(log n) O(1) 平均 内存占用 较小 较大
std::map<std::string, int > ordered_map;
ordered_map["apple" ] = 1 ;
std::unordered_map<std::string, int > unordered_map;
unordered_map["apple" ] = 1 ;
set :元素唯一、自动排序。
multiset :元素可重复、自动排序。
std::set<int > s;
s.insert (1 );
s.insert (1 );
std::multiset<int > ms;
ms.insert (1 );
ms.insert (1 );
双端队列,两端插入删除高效,非严格连续内存。两端操作 O(1),中间操作 O(n)。适用于需要在两端频繁操作。
std::deque<int > dq;
dq.push_front (1 );
dq.push_back (2 );
dq.pop_front ();
dq.pop_back ();
vector :需要随机访问、尾部操作。
list :频繁中间插入删除。
deque :两端频繁操作。
map :需要键值对、有序。
unordered_map :需要键值对、无序但快速。
set :唯一元素、有序。
priority_queue :需要优先级队列。
直接构造元素,避免临时对象。包括 emplace(指定位置)、emplace_back(尾部)、emplace_front(头部)。
std::vector<std::pair<int , std::string>> vec;
vec.push_back (std::make_pair (1 , "hello" ));
vec.emplace_back (1 , "hello" );
管理内存分配。默认 allocator 使用 new/delete,可自定义特殊需求或内存池以提高效率。
template <typename T>
class MyAllocator {
public :
using value_type = T;
T* allocate (size_t n) {
return static_cast <T*>(::operator new (n * sizeof (T)));
}
void deallocate (T* p, size_t ) {
::operator delete (p) ;
}
};
std::vector<int , MyAllocator<int >> vec;
STL 算法 快速排序实现,平均 O(n log n),最坏 O(n²),不稳定排序。可提供自定义比较函数。
std::vector<int > vec = {3 , 1 , 4 , 1 , 5 };
std::sort (vec.begin (), vec.end ());
std::sort (vec.begin (), vec.end (), std::greater <int >());
std::sort (vec.begin (), vec.end (), [](int a, int b) {
return a % 10 < b % 10 ;
});
42. find 和 binary_find 的区别?
find :线性搜索,O(n),适用于未排序序列。
binary_search :二分搜索,O(log n),需要有序序列。
std::vector<int > vec = {1 , 3 , 5 , 7 , 9 };
auto it1 = std::find (vec.begin (), vec.end (), 5 );
bool found = std::binary_search (vec.begin (), vec.end (), 5 );
auto lower = std::lower_bound (vec.begin (), vec.end (), 5 );
auto upper = std::upper_bound (vec.begin (), vec.end (), 5 );
43. for_each 和范围 for 循环的区别?
for_each :算法函数,可配合函数对象。
范围 for :语言特性,更简洁。
std::vector<int > vec = {1 , 2 , 3 , 4 , 5 };
std::for_each(vec.begin (), vec.end (), [](int & x) {
x *= 2 ;
});
for (int & x : vec) {
x *= 2 ;
}
对序列进行变换。一元变换对每个元素应用函数,二元变换对两个序列对应元素应用函数。
std::vector<int > src = {1 , 2 , 3 , 4 , 5 };
std::vector<int > dest (src.size()) ;
std::transform (src.begin (), src.end (), dest.begin (), [](int x) {
return x * x;
});
std::vector<int > src2 = {5 , 4 , 3 , 2 , 1 };
std::vector<int > dest2 (src.size()) ;
std::transform (src.begin (), src.end (), src2. begin (), dest2. begin (), [](int a, int b) {
return a + b;
});
remove :将不需要的元素移到末尾,返回新逻辑终点。
erase :真正删除元素。
std::vector<int > vec = {1 , 2 , 3 , 4 , 5 , 3 , 6 };
auto new_end = std::remove (vec.begin (), vec.end (), 3 );
vec.erase (new_end, vec.end ());
vec.erase (std::remove (vec.begin (), vec.end (), 3 ), vec.end ());
智能指针 独占所有权的智能指针。不能复制,只能移动。自动释放,轻量级,开销接近原始指针。
std::unique_ptr<int > ptr1 = std::make_unique <int >(42 );
std::unique_ptr<int > ptr2 = std::move (ptr1);
std::unique_ptr<FILE, decltype (&fclose) > file (fopen("test.txt" , "r" ), fclose) ;
共享所有权的智能指针。引用计数,多个指针共享对象。引用计数操作原子线程安全。注意循环引用可能导致泄漏。
std::shared_ptr<int > ptr1 = std::make_shared <int >(42 );
std::shared_ptr<int > ptr2 = ptr1;
std::cout << ptr1. use_count () << std::endl;
ptr2. reset ();
std::cout << ptr1. use_count () << std::endl;
解决 shared_ptr 的循环引用问题。弱引用不影响引用计数,作为观察者观察 shared_ptr 管理的对象,通过 lock() 获取 shared_ptr。
class Node {
public :
std::shared_ptr<Node> next;
std::weak_ptr<Node> prev;
};
std::shared_ptr<Node> node1 = std::make_shared <Node>();
std::shared_ptr<Node> node2 = std::make_shared <Node>();
node1->next = node2;
node2->prev = node1;
49. make_shared 和 make_unique 的优势?
异常安全,避免内存泄漏。性能更好,一次内存分配。代码简洁易读。
std::shared_ptr<int > ptr (new int (42 )) ;
auto ptr = std::make_shared <int >(42 );
unique_ptr :独占所有权,最轻量。
shared_ptr :需要共享所有权。
weak_ptr :解决循环引用,观察者模式。
原始指针 :不拥有所有权,仅观察。
class Owner {
std::unique_ptr<Resource> resource;
};
class Observer {
std::weak_ptr<Subject> subject;
};
class Collaborator {
std::shared_ptr<Data> data;
};
第三部分:内存管理与性能
内存管理 特性 new malloc 类型安全 安全 不安全 构造函数 调用 不调用 析构函数 delete 调用 free 不调用 大小计算 自动 手动 失败处理 抛出异常 返回 NULL 重载 可重载 不可重载
MyClass* obj1 = new MyClass ();
MyClass* obj2 = (MyClass*)malloc (sizeof (MyClass));
delete obj1;
free (obj2);
delete :调用析构函数,释放 new 分配的内存。
free :不调用析构函数,释放 malloc 分配的内存。
delete[] :调用数组析构函数。
混用 :new 配 delete,malloc 配 free。
int * p1 = new int ;
delete p1;
int * p2 = new int [10 ];
delete [] p2;
int * p3 = (int *)malloc (sizeof (int ));
free (p3);
int * p4 = new int ;
free (p4);
包含虚函数表指针(有虚函数时)、成员变量(按声明顺序)、内存对齐填充、基类成员在前。
class Base {
public :
virtual void func () {}
int a;
char b;
};
class Derived : public Base {
public :
void func () override {}
int c;
};
数据存储在特定地址边界,提高 CPU 访问效率。规则是按成员最大对齐值对齐,可使用 alignas 控制。
struct Example {
char a;
int b;
char c;
};
struct alignas (16 ) Aligned {
int data[4 ];
};
资源获取即初始化(Resource Acquisition Is Initialization)。构造函数获取资源,析构函数释放资源,保证异常安全。智能指针是其典型应用。
class FileHandler {
public :
FileHandler (const char * filename) {
file = fopen (filename, "r" );
if (!file) throw std::runtime_error ("Cannot open file" );
}
~FileHandler () {
if (file) fclose (file);
}
FILE* get () { return file; }
private :
FILE* file;
};
{
FileHandler fh ("test.txt" ) ;
}
阶段包括分配、初始化、使用、销毁、释放。不同存储期的对象(全局、静态、局部、动态)生命周期不同。
class Lifecycle {
public :
Lifecycle () { std::cout << "构造" << std::endl; }
~Lifecycle () { std::cout << "析构" << std::endl; }
};
Lifecycle global_obj;
void func () {
static Lifecycle static_obj;
Lifecycle local_obj;
auto * dynamic_obj = new Lifecycle ();
delete dynamic_obj;
}
检测工具:Valgrind、AddressSanitizer。预防策略:RAII、智能指针、代码审查。
class ResourceManager {
public :
void addResource (std::shared_ptr<Resource> resource) {
resources.push_back (resource);
}
private :
std::vector<std::shared_ptr<Resource>> resources;
};
场景包括性能优化(减少分配开销)、特殊需求(固定大小块、内存池)、调试目的(跟踪内存使用)。
class MemoryPool {
private :
struct Block {
Block* next;
};
Block* freeList = nullptr ;
size_t blockSize;
std::vector<void *> chunks;
public :
MemoryPool (size_t size) : blockSize (size) {}
void * allocate () {
if (!freeList) {
char * chunk = new char [blockSize * 100 ];
chunks.push_back (chunk);
for (int i = 0 ; i < 100 ; ++i) {
Block* block = reinterpret_cast <Block*>(chunk + i * blockSize);
block->next = freeList;
freeList = block;
}
}
Block* result = freeList;
freeList = freeList->next;
return result;
}
void deallocate (void * ptr) {
Block* block = static_cast <Block*>(ptr);
block->next = freeList;
freeList = block;
}
};
异常处理 三要素:try(可能抛出异常的代码块)、catch(捕获并处理异常)、throw(抛出异常)。
try {
if (error) {
throw std::runtime_error ("Something went wrong" );
}
} catch (const std::runtime_error& e) {
std::cout << "捕获异常:" << e.what () << std::endl;
} catch (...) {
std::cout << "捕获未知异常" << std::endl;
}
基本保证 :无资源泄漏,对象状态有效。
强保证 :操作成功或回滚到原状态。
不抛异常保证 :noexcept,绝不抛出异常。
void basicGuarantee () {
auto * ptr = new int [100 ];
try {
process (ptr);
} catch (...) {
delete [] ptr;
throw ;
}
delete [] ptr;
}
void strongGuarantee (std::vector<int >& vec) {
std::vector<int > backup = vec;
try {
modify (vec);
} catch (...) {
vec = backup;
throw ;
}
}
void noThrowGuarantee () noexcept {
}
指定函数不抛出异常。优化性能,抛出异常时直接 terminate。移动操作通常标记 noexcept。
void safeFunction () noexcept {
}
template <typename T>
void moveIfNoexcept (T& src, T& dest) noexcept (noexcept (T(move(src)))) {
dest = std::move (src);
}
class MyClass {
public :
MyClass (MyClass&& other) noexcept
: data (std::move (other.data)) {}
private :
std::vector<int > data;
};
特性 异常 错误码 性能 较高开销 低开销 可读性 清晰分离 混合逻辑 强制性 强制处理 可忽略 信息量 丰富 有限 适用场景 异常情况 预期错误
int divide (int a, int b) {
if (b == 0 ) {
throw std::invalid_argument ("Division by zero" );
}
return a / b;
}
enum ErrorCode { SUCCESS, DIVISION_BY_ZERO };
ErrorCode divide (int a, int b, int & result) {
if (b == 0 ) {
return DIVISION_BY_ZERO;
}
result = a / b;
return SUCCESS;
}
确保异常安全。自动清理,资源管理(智能指针、文件句柄等),异常传播时资源正确释放。
class ExceptionSafe {
public :
ExceptionSafe () {
resource1 = acquireResource1 ();
resource2 = acquireResource2 ();
}
~ExceptionSafe () {
releaseResource2 (resource2);
releaseResource1 (resource1);
}
private :
Resource* resource1;
Resource* resource2;
};
性能优化 转移资源而非拷贝。避免深拷贝,提高大对象性能。右值引用绑定到临时对象。
class String {
public :
String (const String& other) {
data = new char [strlen (other.data) + 1 ];
strcpy (data, other.data);
}
String (String&& other) noexcept
: data (other.data) {
other.data = nullptr ;
}
private :
char * data;
};
String s1 = "Hello" ;
String s2 = s1;
String s3 = std::move (s1);
String s4 = String ("World" );
保持参数的值类别。转发引用 template T&&,forward 函数保持左值/右值特性,通用引用可绑定左值和右值。
template <typename T>
void wrapper (T&& arg) {
func (std::forward<T>(arg));
}
void func (int & x) { std::cout << "左值引用" << std::endl; }
void func (int && x) { std::cout << "右值引用" << std::endl; }
int a = 10 ;
wrapper (a);
wrapper (10 );
编译器优化,避免不必要的拷贝。NRVO 命名返回值优化。条件通常是返回局部对象。
String createString () {
String result ("Hello" ) ;
return result;
}
String createString () {
return String ("Hello" );
}
String s = createString ();
constexpr 编译期计算,const 常量传播,inline 内联函数,模板元编程编译期计算。
constexpr int factorial (int n) {
return n <= 1 ? 1 : n * factorial (n - 1 );
}
constexpr int result = factorial (5 );
template <int N>
struct Factorial {
static const int value = N * Factorial<N - 1 >::value;
};
template <>
struct Factorial <0 > {
static const int value = 1 ;
};
constexpr int fact5 = Factorial<5 >::value;
遵循局部性原理(时间和空间局部性),数据结构采用连续内存访问,循环优化提高缓存命中率。
void badAccess (int matrix[1000 ][1000 ]) {
for (int j = 0 ; j < 1000 ; ++j) {
for (int i = 0 ; i < 1000 ; ++i) {
matrix[i][j]++;
}
}
}
void goodAccess (int matrix[1000 ][1000 ]) {
for (int i = 0 ; i < 1000 ; ++i) {
for (int j = 0 ; j < 1000 ; ++j) {
matrix[i][j]++;
}
}
}
reserve 预分配容量,resize 改变大小并初始化,shrink_to_fit 释放多余容量。避免重复分配。
std::vector<int > vec;
vec.reserve (1000 );
for (int i = 0 ; i < 1000 ; ++i) {
vec.push_back (i);
}
vec.resize (2000 );
vec.shrink_to_fit ();
常用工具:gprof、perf、Valgrind、Intel VTune。
g++ -g -pg program.cpp -o program
./program
gprof program gmon.out > analysis.txt
perf record ./program
perf report
第四部分:高级特性
多线程编程 支持 std::thread,join() 等待结束,detach() 分离,hardware_concurrency() 获取硬件并发数。
#include <thread>
#include <iostream>
void workerFunction (int id) {
std::cout << "Worker " << id << " is running" << std::endl;
}
int main () {
std::thread t1 (workerFunction, 1 ) ;
std::thread t2 (workerFunction, 2 ) ;
t1. join ();
t2. join ();
unsigned int cores = std::thread::hardware_concurrency ();
std::cout << "CPU cores: " << cores << std::endl;
return 0 ;
}
保护共享资源。std::mutex 基本锁,std::lock_guard RAII 管理,std::unique_lock 灵活管理,std::recursive_mutex 可重入锁。
#include <mutex>
#include <thread>
#include <vector>
class Counter {
private :
int value = 0 ;
std::mutex mtx;
public :
void increment () {
std::lock_guard<std::mutex> lock (mtx) ;
++value;
}
int getValue () {
std::unique_lock<std::mutex> lock (mtx) ;
int result = value;
lock.unlock ();
return result;
}
};
void worker (Counter& counter) {
for (int i = 0 ; i < 1000 ; ++i) {
counter.increment ();
}
}
int main () {
Counter counter;
std::vector<std::thread> threads;
for (int i = 0 ; i < 10 ; ++i) {
threads.emplace_back (worker, std::ref (counter));
}
for (auto & t : threads) {
t.join ();
}
std::cout << "Final value: " << counter.getValue () << std::endl;
return 0 ;
}
实现线程同步。std::condition_variable,wait() 等待条件满足,notify_one() 唤醒一个,notify_all() 唤醒所有。
#include <condition_variable>
#include <queue>
#include <thread>
template <typename T>
class ThreadSafeQueue {
private :
std::queue<T> queue;
std::mutex mtx;
std::condition_variable cv;
bool done = false ;
public :
void push (const T& item) {
{
std::lock_guard<std::mutex> lock (mtx) ;
queue.push (item);
}
cv.notify_one ();
}
bool pop (T& item) {
std::unique_lock<std::mutex> lock (mtx) ;
cv.wait (lock, [this ] { return !queue.empty () || done; });
if (queue.empty () && done) {
return false ;
}
item = queue.front ();
queue.pop ();
return true ;
}
void setDone () {
{
std::lock_guard<std::mutex> lock (mtx) ;
done = true ;
}
cv.notify_all ();
}
};
无锁编程。std::atomic,memory_order 内存序,CAS 比较并交换。
#include <atomic>
#include <thread>
#include <vector>
class AtomicCounter {
private :
std::atomic<int > value{0 };
public :
void increment () {
value.fetch_add (1 , std::memory_order_relaxed);
}
int getValue () const {
return value.load (std::memory_order_acquire);
}
bool compareAndSwap (int expected, int desired) {
return value.compare_exchange_weak (expected, desired);
}
};
template <typename T>
struct LockFreeNode {
T data;
std::atomic<LockFreeNode*> next;
};
template <typename T>
class LockFreeStack {
private :
std::atomic<LockFreeNode<T>*> head{nullptr };
public :
void push (const T& item) {
LockFreeNode<T>* newNode = new LockFreeNode<T>{item, head.load ()};
while (!head.compare_exchange_weak (newNode->next, newNode)) {
}
}
};
Meyers 单例(C++11 保证线程安全),双重检查锁定,std::call_once。
class Singleton {
public :
static Singleton& getInstance () {
static Singleton instance;
return instance;
}
void doSomething () {
std::cout << "Doing something" << std::endl;
}
private :
Singleton () = default ;
~Singleton () = default ;
Singleton (const Singleton&) = delete ;
Singleton& operator =(const Singleton&) = delete ;
};
class CallOnceSingleton {
private :
static std::once_flag flag;
static CallOnceSingleton* instance;
CallOnceSingleton () = default ;
public :
static CallOnceSingleton& getInstance () {
std::call_once (flag, []() {
instance = new CallOnceSingleton ();
});
return *instance;
}
};
std::once_flag CallOnceSingleton::flag;
CallOnceSingleton* CallOnceSingleton::instance = nullptr ;
76. future 和 promise 的使用?
异步编程。std::future 获取结果,std::promise 设置结果,std::async 异步执行,std::packaged_task 包装可调用对象。
#include <future>
#include <iostream>
#include <chrono>
int asyncFunction () {
std::this_thread::sleep_for (std::chrono::seconds (2 ));
return 42 ;
}
void asyncExample () {
std::future<int > future = std::async (std::launch::async, asyncFunction);
std::cout << "Doing other work..." << std::endl;
int result = future.get ();
std::cout << "Result: " << result << std::endl;
}
void promiseExample () {
std::promise<int > promise;
std::future<int > future = promise.get_future ();
std::thread producer ([&promise]() {
std::this_thread::sleep_for(std::chrono::seconds(1 ));
promise.set_value(100 );
}) ;
std::thread consumer ([&future]() {
int value = future.get();
std::cout << "Received: " << value << std::endl;
}) ;
producer.join ();
consumer.join ();
}
void packagedTaskExample () {
std::packaged_task<int () > task ([]() { return 123 ; }) ;
std::future<int > future = task.get_future ();
std::thread t (std::move(task)) ;
t.detach ();
int result = future.get ();
std::cout << "Packaged task result: " << result << std::endl;
}
管理线程资源。固定数量线程,任务队列缓存待执行任务,工作线程从队列取任务执行。
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <future>
class ThreadPool {
private :
std::vector<std::thread> workers;
std::queue<std::function<void ()>> tasks;
std::mutex queue_mutex;
std::condition_variable condition;
bool stop = false ;
public :
ThreadPool (size_t threads) {
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 <typename F, typename ... Args>
auto enqueue (F&& f, Args&&... args)
-> std::future<typename std::result_of<F (Args...) >::type> {
using return_type = typename std::result_of<F (Args...)>::type;
auto task = std::make_shared<std::packaged_task<return_type ()>>(
std::bind (std::forward<F>(f), std::forward<Args>(args)...));
std::future<return_type> result = task->get_future ();
{
std::unique_lock<std::mutex> lock (queue_mutex) ;
if (stop) {
throw std::runtime_error ("enqueue on stopped ThreadPool" );
}
tasks.emplace ([task] { (*task)(); });
}
condition.notify_one ();
return result;
}
~ThreadPool () {
{
std::unique_lock<std::mutex> lock (queue_mutex) ;
stop = true ;
}
condition.notify_all ();
for (std::thread& worker : workers) {
worker.join ();
}
}
};
void threadPoolExample () {
ThreadPool pool (4 ) ;
std::vector<std::future<int >> results;
for (int i = 0 ; i < 8 ; ++i) {
results.emplace_back (pool.enqueue ([i]() {
std::this_thread::sleep_for (std::chrono::seconds (1 ));
return i * i;
}));
}
for (auto && result : results) {
std::cout << result.get () << std::endl;
}
}
现代 C++ 特性 自动类型推导。简化代码,减少冗长类型名,简化迭代器,C++14 支持函数返回值推导。注意可能降低可读性。
#include <vector>
#include <map>
#include <string>
void autoExample () {
auto i = 42 ;
auto d = 3.14 ;
auto s = "hello" ;
std::vector<int > vec = {1 , 2 , 3 , 4 , 5 };
for (auto it = vec.begin (); it != vec.end (); ++it) {
std::cout << *it << " " ;
}
for (auto & item : vec) {
item *= 2 ;
}
std::map<std::string, std::vector<int >> complex_map;
auto & map_ref = complex_map;
auto add = [](auto a, auto b) { return a + b; };
auto result = add (3 , 4 );
auto result2 = add (3.14 , 2.71 );
}
匿名函数。语法 [捕获] -> 返回类型 { 函数体 }。捕获方式包括值、引用、混合。应用于 STL 算法、回调函数。
#include <algorithm>
#include <vector>
#include <iostream>
void lambdaExample () {
std::vector<int > numbers = {1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 };
auto square = [](int x) { return x * x; };
std::cout << "5 squared: " << square (5 ) << std::endl;
int factor = 2 ;
auto multiply = [factor](int x) { return x * factor; };
std::cout << "5 * 2: " << multiply (5 ) << std::endl;
int sum = 0 ;
std::for_each(numbers.begin (), numbers.end (), [&sum](int x) {
sum += x;
});
std::cout << "Sum: " << sum << std::endl;
int threshold = 5 ;
int count = 0 ;
std::for_each(numbers.begin (), numbers.end (), [threshold, &count](int x) {
if (x > threshold) count++;
});
std::cout << "Numbers > 5: " << count << std::endl;
int accumulator = 0 ;
auto mutableLambda = [accumulator](int x) mutable {
accumulator += x;
return accumulator;
};
std::cout << mutableLambda (10 ) << std::endl;
std::cout << mutableLambda (20 ) << std::endl;
auto genericLambda = [](auto a, auto b) { return a + b; };
std::cout << genericLambda (3 , 4 ) << std::endl;
std::cout << genericLambda (3.14 , 2.71 ) << std::endl;
}
编译期常量。提高运行时性能。函数和变量都可以标记。限制只能使用编译期可用操作。
constexpr int MAX_SIZE = 100 ;
constexpr double PI = 3.14159265359 ;
constexpr int factorial (int n) {
return n <= 1 ? 1 : n * factorial (n - 1 );
}
constexpr int fact5 = factorial (5 );
class Point {
private :
double x_, y_;
public :
constexpr Point (double x, double y) : x_(x), y_(y) { }
constexpr double x () const { return x_; }
constexpr double y () const { return y_; }
constexpr double distance () const { return x_ * x_ + y_ * y_; }
};
constexpr Point p (3.0 , 4.0 ) ;
constexpr double dist = p.distance ();
class Complex {
private :
double real_, imag_;
public :
constexpr Complex (double real, double imag) : real_(real), imag_(imag) { }
constexpr Complex operator +(const Complex& other) const {
return Complex (real_ + other.real_, imag_ + other.imag_);
}
constexpr double real () const { return real_; }
constexpr double imag () const { return imag_; }
};
constexpr Complex c1 (1.0 , 2.0 ) ;
constexpr Complex c2 (3.0 , 4.0 ) ;
constexpr Complex c3 = c1 + c2;
简化遍历。语法 for (declaration : range) statement。适用于数组、容器、任何提供 begin/end 的类型。注意拷贝 vs 引用、const 修饰。
#include <vector>
#include <map>
#include <iostream>
#include <string>
void rangeForExample () {
int arr[] = {1 , 2 , 3 , 4 , 5 };
for (int x : arr) {
std::cout << x << " " ;
}
std::cout << std::endl;
std::vector<std::string> words = {"hello" , "world" , "c++" };
for (const auto & word : words) {
std::cout << word << " " ;
}
std::cout << std::endl;
for (auto & word : words) {
word += "!" ;
}
std::map<int , std::string> number_map = {{1 , "one" }, {2 , "two" }, {3 , "three" }};
for (const auto & [key, value] : number_map) {
std::cout << key << ": " << value << std::endl;
}
class MyContainer {
private :
std::vector<int > data_;
public :
MyContainer (std::initializer_list<int > init) : data_ (init) {}
auto begin () { return data_.begin (); }
auto end () { return data_.end (); }
auto begin () const { return data_.begin (); }
auto end () const { return data_.end (); }
};
MyContainer container = {10 , 20 , 30 };
for (int x : container) {
std::cout << x << " " ;
}
std::cout << std::endl;
}
C++17 解包复合类型。语法 auto [a, b] = pair。适用于 pair、tuple、数组、结构体。简化多返回值处理。
#include <tuple>
#include <map>
#include <array>
#include <string>
#include <iostream>
void structuredBindingExample () {
std::pair<int , std::string> p = {42 , "answer" };
auto [id, name] = p;
std::cout << "id: " << id << ", name: " << name << std::endl;
std::tuple<int , double , std::string> t = {1 , 3.14 , "pi" };
auto [i, d, s] = t;
std::cout << i << ", " << d << ", " << s << std::endl;
int arr[3 ] = {10 , 20 , 30 };
auto [a, b, c] = arr;
std::cout << a << ", " << b << ", " << c << std::endl;
struct Point { double x, y; };
Point pt = {3.0 , 4.0 };
auto [x, y] = pt;
std::cout << "Point: (" << x << ", " << y << ")" << std::endl;
std::map<std::string, int > scores = {{"Alice" , 95 }, {"Bob" , 87 }, {"Charlie" , 92 }};
for (const auto & [name, score] : scores) {
std::cout << name << ": " << score << std::endl;
}
auto divide = [](double numerator, double denominator) -> std::pair<double , bool > {
if (denominator == 0 ) {
return {0.0 , false };
}
return {numerator / denominator, true };
};
auto [result, success] = divide (10.0 , 2.0 );
if (success) {
std::cout << "Result: " << result << std::endl;
}
}
表示可能不存在的值。替代空指针,类型安全。避免特殊值如 -1 表示无效。操作方法包括 value()、value_or()、has_value()。
#include <optional>
#include <string>
#include <iostream>
#include <vector>
std::optional<int > parseInt (const std::string& s) {
try {
return std::stoi (s);
} catch (...) {
return std::nullopt ;
}
}
std::optional<std::string> findUser (int id) {
static std::map<int , std::string> users = {{1 , "Alice" }, {2 , "Bob" }, {3 , "Charlie" }};
auto it = users.find (id);
if (it != users.end ()) {
return it->second;
}
return std::nullopt ;
}
void optionalExample () {
auto result1 = parseInt ("123" );
auto result2 = parseInt ("abc" );
if (result1) {
std::cout << "Parsed: " << result1. value () << std::endl;
}
if (result2. has_value ()) {
std::cout << "Parsed: " << result2. value () << std::endl;
} else {
std::cout << "Invalid number" << std::endl;
}
int value = result2. value_or (0 );
std::cout << "Value: " << value << std::endl;
auto user = findUser (2 );
std::cout << "User: " << user.value_or ("Unknown" ) << std::endl;
class Config {
private :
std::optional<std::string> database_url_;
std::optional<int > timeout_;
public :
void setDatabaseUrl (const std::string& url) {
database_url_ = url;
}
std::string getDatabaseUrl () const {
return database_url_.value_or ("localhost:5432" );
}
void setTimeout (int seconds) {
timeout_ = seconds;
}
int getTimeout () const {
return timeout_.value_or (30 );
}
};
Config config;
config.setTimeout (60 );
std::cout << "Database: " << config.getDatabaseUrl () << std::endl;
std::cout << "Timeout: " << config.getTimeout () << std::endl;
}
类型安全的联合体。编译期类型检查。访问方式包括 std::get、std::visit。应用场景包括多类型选择、解析结果。
#include <variant>
#include <string>
#include <iostream>
#include <vector>
using Value = std::variant<int , double , std::string>;
void variantExample () {
Value v1 = 42 ;
Value v2 = 3.14 ;
Value v3 = "hello" ;
if (std::holds_alternative <int >(v1)) {
int int_val = std::get <int >(v1);
std::cout << "Int value: " << int_val << std::endl;
}
if (auto * str_ptr = std::get_if <std::string>(&v3)) {
std::cout << "String value: " << *str_ptr << std::endl;
}
auto visitor = [](auto && arg) {
using T = std::decay_t <decltype (arg)>;
if constexpr (std::is_same_v<T, int >) {
std::cout << "Int: " << arg << std::endl;
} else if constexpr (std::is_same_v<T, double >) {
std::cout << "Double: " << arg << std::endl;
} else if constexpr (std::is_same_v<T, std::string>) {
std::cout << "String: " << arg << std::endl;
}
};
std::visit (visitor, v1);
std::visit (visitor, v2);
std::visit (visitor, v3);
std::variant<int , std::string> parseNumber (const std::string& s) {
try {
return std::stoi (s);
} catch (...) {
return "Invalid number: " + s;
}
}
auto result = parseNumber ("123" );
std::visit ([](auto && arg) {
std::cout << "Parse result: " << arg << std::endl;
}, result);
std::vector<Value> values = {1 , 2.5 , "three" , 4 , 5.5 };
for (const auto & val : values) {
std::visit (visitor, val);
}
}
类型安全的任意类型容器。类型擦除,存储任何类型。访问时需要类型检查,保存类型信息。
#include <any>
#include <string>
#include <iostream>
#include <vector>
#include <typeinfo>
void anyExample () {
std::any a = 42 ;
a = 3.14 ;
a = std::string ("hello" );
if (a.type () == typeid (std::string)) {
std::string str = std::any_cast <std::string>(a);
std::cout << "String: " << str << std::endl;
}
try {
int int_val = std::any_cast <int >(a);
} catch (const std::bad_any_cast& e) {
std::cout << "Bad cast: " << e.what () << std::endl;
}
if (auto * str_ptr = std::any_cast <std::string>(&a)) {
std::cout << "String pointer: " << *str_ptr << std::endl;
}
std::vector<std::any> values;
values.push_back (42 );
values.push_back (3.14 );
values.push_back (std::string ("world" ));
values.push_back (std::vector<int >{1 , 2 , 3 });
for (const auto & val : values) {
if (val.type () == typeid (int )) {
std::cout << "Int: " << std::any_cast <int >(val) << std::endl;
} else if (val.type () == typeid (double )) {
std::cout << "Double: " << std::any_cast <double >(val) << std::endl;
} else if (val.type () == typeid (std::string)) {
std::cout << "String: " << std::any_cast <std::string>(val) << std::endl;
} else if (val.type () == typeid (std::vector<int >)) {
auto vec = std::any_cast<std::vector<int >>(val);
std::cout << "Vector: " ;
for (int x : vec) std::cout << x << " " ;
std::cout << std::endl;
}
}
void printAny (const std::any& value) {
if (value.type () == typeid (int )) {
std::cout << "Int: " << std::any_cast <int >(value) << std::endl;
} else if (value.type () == typeid (std::string)) {
std::cout << "String: " << std::any_cast <std::string>(value) << std::endl;
} else {
std::cout << "Unknown type: " << value.type ().name () << std::endl;
}
}
printAny (123 );
printAny (std::string ("test" ));
class Config {
private :
std::map<std::string, std::any> config_;
public :
template <typename T>
void set (const std::string& key, const T& value) {
config_[key] = value;
}
template <typename T>
T get (const std::string& key, const T& default_value = T{}) const {
auto it = config_.find (key);
if (it != config_.end () && it->second.type () == typeid (T)) {
return std::any_cast <T>(it->second);
}
return default_value;
}
};
Config config;
config.set ("timeout" , 30 );
config.set ("name" , std::string ("MyApp" ));
config.set ("version" , 1.5 );
int timeout = config.get <int >("timeout" , 60 );
std::string name = config.get <std::string>("name" , "Unknown" );
double version = config.get <double >("version" , 1.0 );
std::cout << "Config: " << timeout << ", " << name << ", " << version << std::endl;
}
第五部分:设计模式与架构
设计模式 确保类只有一个实例。饿汉式(启动时创建)、懒汉式(首次使用时创建)。C++11 保证 Meyers 单例线程安全。
class EagerSingleton {
private :
static EagerSingleton instance;
EagerSingleton () = default ;
public :
static EagerSingleton& getInstance () {
return instance;
}
void doSomething () {
std::cout << "Eager singleton working" << std::endl;
}
};
EagerSingleton EagerSingleton::instance;
class LazySingleton {
private :
LazySingleton () = default ;
~LazySingleton () = default ;
LazySingleton (const LazySingleton&) = delete ;
LazySingleton& operator =(const LazySingleton&) = delete ;
public :
static LazySingleton& getInstance () {
static LazySingleton instance;
return instance;
}
void doSomething () {
std::cout << "Lazy singleton working" << std::endl;
}
};
void singletonExample () {
LazySingleton& s1 = LazySingleton::getInstance ();
LazySingleton& s2 = LazySingleton::getInstance ();
std::cout << "Same instance: " << (&s1 == &s2) << std::endl;
s1. doSomething ();
}
创建对象而不暴露创建逻辑。简单工厂(一个工厂类)、工厂方法(每个产品对应工厂)、抽象工厂(产品族)。
#include <memory>
#include <string>
#include <iostream>
class Shape {
public :
virtual ~Shape () = default ;
virtual void draw () const = 0 ;
};
class Circle : public Shape {
public :
void draw () const override {
std::cout << "Drawing Circle" << std::endl;
}
};
class Rectangle : public Shape {
public :
void draw () const override {
std::cout << "Drawing Rectangle" << std::endl;
}
};
class Triangle : public Shape {
public :
void draw () const override {
std::cout << "Drawing Triangle" << std::endl;
}
};
class SimpleShapeFactory {
public :
enum class ShapeType { CIRCLE, RECTANGLE, TRIANGLE };
static std::unique_ptr<Shape> createShape (ShapeType type) {
switch (type) {
case ShapeType::CIRCLE:
return std::make_unique <Circle>();
case ShapeType::RECTANGLE:
return std::make_unique <Rectangle>();
case ShapeType::TRIANGLE:
return std::make_unique <Triangle>();
default :
return nullptr ;
}
}
};
class ShapeFactory {
public :
virtual ~ShapeFactory () = default ;
virtual std::unique_ptr<Shape> createShape () const = 0 ;
};
class CircleFactory : public ShapeFactory {
public :
std::unique_ptr<Shape> createShape () const override {
return std::make_unique <Circle>();
}
};
class RectangleFactory : public ShapeFactory {
public :
std::unique_ptr<Shape> createShape () const override {
return std::make_unique <Rectangle>();
}
};
void factoryExample () {
auto circle = SimpleShapeFactory::createShape (SimpleShapeFactory::ShapeType::CIRCLE);
auto rectangle = SimpleShapeFactory::createShape (SimpleShapeFactory::ShapeType::RECTANGLE);
circle->draw ();
rectangle->draw ();
CircleFactory circleFactory;
RectangleFactory rectangleFactory;
auto circle2 = circleFactory.createShape ();
auto rectangle2 = rectangleFactory.createShape ();
circle2->draw ();
rectangle2->draw ();
}
定义对象间一对多依赖。主题维护观察者列表,观察者接收通知。松耦合。
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
class Observer {
public :
virtual ~Observer () = default ;
virtual void update (const std::string& message) = 0 ;
};
class Subject {
public :
virtual ~Subject () = default ;
virtual void attach (Observer* observer) = 0 ;
virtual void detach (Observer* observer) = 0 ;
virtual void notify (const std::string& message) = 0 ;
};
class NewsAgency : public Subject {
private :
std::vector<Observer*> observers;
std::string latestNews;
public :
void attach (Observer* observer) override {
observers.push_back (observer);
}
void detach (Observer* observer) override {
observers.erase (
std::remove (observers.begin (), observers.end (), observer),
observers.end ());
}
void notify (const std::string& message) override {
latestNews = message;
for (Observer* observer : observers) {
observer->update (message);
}
}
void setNews (const std::string& news) {
notify (news);
}
};
class NewsSubscriber : public Observer {
private :
std::string name;
public :
NewsSubscriber (const std::string& subscriberName) : name (subscriberName) {}
void update (const std::string& message) override {
std::cout << name << " received news: " << message << std::endl;
}
};
void observerExample () {
NewsAgency agency;
NewsSubscriber alice ("Alice" ) ;
NewsSubscriber bob ("Bob" ) ;
NewsSubscriber charlie ("Charlie" ) ;
agency.attach (&alice);
agency.attach (&bob);
agency.attach (&charlie);
agency.setNews ("Breaking: C++20 is released!" );
agency.detach (&bob);
agency.setNews ("Update: New C++ features available!" );
}
定义算法族,可互换使用。策略接口定义算法,具体策略实现算法,上下文使用策略对象。
#include <memory>
#include <vector>
#include <algorithm>
#include <iostream>
class SortStrategy {
public :
virtual ~SortStrategy () = default ;
virtual void sort (std::vector<int >& data) const = 0 ;
};
class BubbleSort : public SortStrategy {
public :
void sort (std::vector<int >& data) const override {
std::cout << "Using Bubble Sort" << std::endl;
int n = data.size ();
for (int i = 0 ; i < n - 1 ; ++i) {
for (int j = 0 ; j < n - i - 1 ; ++j) {
if (data[j] > data[j + 1 ]) {
std::swap (data[j], data[j + 1 ]);
}
}
}
}
};
class QuickSort : public SortStrategy {
public :
void sort (std::vector<int >& data) const override {
std::cout << "Using Quick Sort" << std::endl;
std::sort (data.begin (), data.end ());
}
};
class InsertionSort : public SortStrategy {
public :
void sort (std::vector<int >& data) const override {
std::cout << "Using Insertion Sort" << std::endl;
for (size_t i = 1 ; i < data.size (); ++i) {
int key = data[i];
int j = static_cast <int >(i) - 1 ;
while (j >= 0 && data[j] > key) {
data[j + 1 ] = data[j];
j--;
}
data[j + 1 ] = key;
}
}
};
class Sorter {
private :
std::unique_ptr<SortStrategy> strategy;
public :
void setStrategy (std::unique_ptr<SortStrategy> newStrategy) {
strategy = std::move (newStrategy);
}
void sort (std::vector<int >& data) const {
if (strategy) {
strategy->sort (data);
}
}
};
void strategyExample () {
std::vector<int > data = {64 , 34 , 25 , 12 , 22 , 11 , 90 };
Sorter sorter;
sorter.setStrategy (std::make_unique <BubbleSort>());
auto data1 = data;
sorter.sort (data1);
sorter.setStrategy (std::make_unique <QuickSort>());
auto data2 = data;
sorter.sort (data2);
sorter.setStrategy (std::make_unique <InsertionSort>());
auto data3 = data;
sorter.sort (data3);
}
动态添加对象功能。组件接口定义基础,具体组件实现基础,装饰器添加额外功能。
#include <string>
#include <iostream>
#include <memory>
class Coffee {
public :
virtual ~Coffee () = default ;
virtual std::string getDescription () const = 0 ;
virtual double cost () const = 0 ;
};
class SimpleCoffee : public Coffee {
public :
std::string getDescription () const override {
return "Simple Coffee" ;
}
double cost () const override {
return 2.0 ;
}
};
class CoffeeDecorator : public Coffee {
private :
std::unique_ptr<Coffee> coffee;
public :
CoffeeDecorator (std::unique_ptr<Coffee> c) : coffee (std::move (c)) {}
std::string getDescription () const override {
return coffee->getDescription ();
}
double cost () const override {
return coffee->cost ();
}
protected :
Coffee* getCoffee () const {
return coffee.get ();
}
};
class MilkDecorator : public CoffeeDecorator {
public :
MilkDecorator (std::unique_ptr<Coffee> c) : CoffeeDecorator (std::move (c)) {}
std::string getDescription () const override {
return getCoffee ()->getDescription () + ", Milk" ;
}
double cost () const override {
return getCoffee ()->cost () + 0.5 ;
}
};
class SugarDecorator : public CoffeeDecorator {
public :
SugarDecorator (std::unique_ptr<Coffee> c) : CoffeeDecorator (std::move (c)) {}
std::string getDescription () const override {
return getCoffee ()->getDescription () + ", Sugar" ;
}
double cost () const override {
return getCoffee ()->cost () + 0.2 ;
}
};
class VanillaDecorator : public CoffeeDecorator {
public :
VanillaDecorator (std::unique_ptr<Coffee> c) : CoffeeDecorator (std::move (c)) {}
std::string getDescription () const override {
return getCoffee ()->getDescription () + ", Vanilla" ;
}
double cost () const override {
return getCoffee ()->cost () + 0.7 ;
}
};
void decoratorExample () {
auto coffee = std::make_unique <SimpleCoffee>();
std::cout << coffee->getDescription () << " $" << coffee->cost () << std::endl;
auto milkCoffee = std::make_unique <MilkDecorator>(std::make_unique <SimpleCoffee>());
std::cout << milkCoffee->getDescription () << " $" << milkCoffee->cost () << std::endl;
auto milkSugarCoffee = std::make_unique <SugarDecorator>(
std::make_unique <MilkDecorator>(std::make_unique <SimpleCoffee>()));
std::cout << milkSugarCoffee->getDescription () << " $" << milkSugarCoffee->cost () << std::endl;
auto complexCoffee = std::make_unique <VanillaDecorator>(
std::make_unique <SugarDecorator>(
std::make_unique <MilkDecorator>(std::make_unique <SimpleCoffee>())));
std::cout << complexCoffee->getDescription () << " $" << complexCoffee->cost () << std::endl;
}
使不兼容接口协同工作。目标接口客户端期望,适配者现有接口,适配器转换接口。
#include <string>
#include <iostream>
#include <memory>
class MediaPlayer {
public :
virtual ~MediaPlayer () = default ;
virtual void play (const std::string& audioType, const std::string& fileName) = 0 ;
};
class AdvancedMediaPlayer {
public :
virtual ~AdvancedMediaPlayer () = default ;
virtual void playVlc (const std::string& fileName) = 0 ;
virtual void playMp4 (const std::string& fileName) = 0 ;
};
class VlcPlayer : public AdvancedMediaPlayer {
public :
void playVlc (const std::string& fileName) override {
std::cout << "Playing vlc file: " << fileName << std::endl;
}
void playMp4 (const std::string& fileName) override {
}
};
class Mp4Player : public AdvancedMediaPlayer {
public :
void playVlc (const std::string& fileName) override {
}
void playMp4 (const std::string& fileName) override {
std::cout << "Playing mp4 file: " << fileName << std::endl;
}
};
class MediaAdapter : public MediaPlayer {
private :
std::unique_ptr<AdvancedMediaPlayer> advancedMusicPlayer;
public :
MediaAdapter (const std::string& audioType) {
if (audioType == "vlc" ) {
advancedMusicPlayer = std::make_unique <VlcPlayer>();
} else if (audioType == "mp4" ) {
advancedMusicPlayer = std::make_unique <Mp4Player>();
}
}
void play (const std::string& audioType, const std::string& fileName) override {
if (audioType == "vlc" ) {
advancedMusicPlayer->playVlc (fileName);
} else if (audioType == "mp4" ) {
advancedMusicPlayer->playMp4 (fileName);
}
}
};
class AudioPlayer : public MediaPlayer {
private :
std::unique_ptr<MediaAdapter> mediaAdapter;
public :
void play (const std::string& audioType, const std::string& fileName) override {
if (audioType == "mp3" ) {
std::cout << "Playing mp3 file: " << fileName << std::endl;
}
else if (audioType == "vlc" || audioType == "mp4" ) {
mediaAdapter = std::make_unique <MediaAdapter>(audioType);
mediaAdapter->play (audioType, fileName);
} else {
std::cout << "Invalid media. " << audioType << " format not supported" << std::endl;
}
}
};
void adapterExample () {
AudioPlayer player;
player.play ("mp3" , "song.mp3" );
player.play ("mp4" , "video.mp4" );
player.play ("vlc" , "movie.vlc" );
player.play ("avi" , "video.avi" );
}
将请求封装为对象。命令接口声明执行,具体命令实现,调用者调用执行,接收者执行操作。
#include <string>
#include <iostream>
#include <vector>
#include <memory>
class Command {
public :
virtual ~Command () = default ;
virtual void execute () = 0 ;
virtual void undo () = 0 ;
};
class Light {
public :
void turnOn () {
std::cout << "Light is ON" << std::endl;
isOn = true ;
}
void turnOff () {
std::cout << "Light is OFF" << std::endl;
isOn = false ;
}
bool getState () const { return isOn; }
private :
bool isOn = false ;
};
class Stereo {
public :
void on () { std::cout << "Stereo is ON" << std::endl; }
void off () { std::cout << "Stereo is OFF" << std::endl; }
void setCd () { std::cout << "Stereo is set for CD input" << std::endl; }
void setVolume (int volume) { std::cout << "Stereo volume set to " << volume << std::endl; }
};
class LightOnCommand : public Command {
private :
Light* light;
public :
LightOnCommand (Light* l) : light (l) {}
void execute () override { light->turnOn (); }
void undo () override { light->turnOff (); }
};
class LightOffCommand : public Command {
private :
Light* light;
public :
LightOffCommand (Light* l) : light (l) {}
void execute () override { light->turnOff (); }
void undo () override { light->turnOn (); }
};
class StereoOnWithCdCommand : public Command {
private :
Stereo* stereo;
public :
StereoOnWithCdCommand (Stereo* s) : stereo (s) {}
void execute () override {
stereo->on ();
stereo->setCd ();
stereo->setVolume (11 );
}
void undo () override { stereo->off (); }
};
class RemoteControl {
private :
std::vector<std::unique_ptr<Command>> undoStack;
std::unique_ptr<Command> currentCommand;
public :
void setCommand (std::unique_ptr<Command> command) {
currentCommand = std::move (command);
}
void buttonWasPressed () {
if (currentCommand) {
currentCommand->execute ();
undoStack.push_back (std::move (currentCommand));
}
}
void undoButtonWasPressed () {
if (!undoStack.empty ()) {
auto lastCommand = std::move (undoStack.back ());
undoStack.pop_back ();
lastCommand->undo ();
}
}
};
void commandExample () {
RemoteControl remote;
Light livingRoomLight;
Stereo stereo;
remote.setCommand (std::make_unique <LightOnCommand>(&livingRoomLight));
remote.buttonWasPressed ();
remote.setCommand (std::make_unique <StereoOnWithCdCommand>(&stereo));
remote.buttonWasPressed ();
remote.undoButtonWasPressed ();
remote.undoButtonWasPressed ();
}
定义算法骨架,子类实现具体步骤。抽象类定义模板方法和抽象步骤,具体类实现具体步骤。
#include <iostream>
#include <string>
class DataProcessor {
public :
void processData () {
loadData ();
if (validateData ()) {
transformData ();
saveData ();
} else {
std::cout << "Data validation failed" << std::endl;
}
cleanup ();
}
protected :
virtual void loadData () = 0 ;
virtual void transformData () = 0 ;
virtual void saveData () = 0 ;
virtual bool validateData () { return true ; }
virtual void cleanup () { std::cout << "Default cleanup" << std::endl; }
};
class CSVProcessor : public DataProcessor {
protected :
void loadData () override { std::cout << "Loading CSV data" << std::endl; }
void transformData () override { std::cout << "Transforming CSV data" << std::endl; }
void saveData () override { std::cout << "Saving CSV data" << std::endl; }
bool validateData () override {
std::cout << "Validating CSV format" << std::endl;
return true ;
}
void cleanup () override { std::cout << "CSV specific cleanup" << std::endl; }
};
class JSONProcessor : public DataProcessor {
protected :
void loadData () override { std::cout << "Loading JSON data" << std::endl; }
void transformData () override { std::cout << "Transforming JSON data" << std::endl; }
void saveData () override { std::cout << "Saving JSON data" << std::endl; }
bool validateData () override {
std::cout << "Validating JSON structure" << std::endl;
return false ;
}
};
class XMLProcessor : public DataProcessor {
protected :
void loadData () override { std::cout << "Loading XML data" << std::endl; }
void transformData () override { std::cout << "Transforming JSON data" << std::endl; }
void saveData () override { std::cout << "Saving XML data" << std::endl; }
};
void templateMethodExample () {
std::cout << "Processing CSV:" << std::endl;
CSVProcessor csvProcessor;
csvProcessor.processData ();
std::cout << "\nProcessing JSON:" << std::endl;
JSONProcessor jsonProcessor;
jsonProcessor.processData ();
std::cout << "\nProcessing XML:" << std::endl;
XMLProcessor xmlProcessor;
xmlProcessor.processData ();
}
允许对象在内部状态改变时改变行为。状态接口定义行为,具体状态实现行为,上下文维护当前状态。
#include <iostream>
#include <string>
#include <memory>
class Context ;
class State {
public :
virtual ~State () = default ;
virtual void insertCoin (Context* context) = 0 ;
virtual void ejectCoin (Context* context) = 0 ;
virtual void turnCrank (Context* context) = 0 ;
virtual void dispense (Context* context) = 0 ;
virtual std::string getName () const = 0 ;
};
class Context {
private :
std::unique_ptr<State> currentState;
int count = 0 ;
public :
Context (std::unique_ptr<State> initialState) : currentState (std::move (initialState)) {}
void setState (std::unique_ptr<State> newState) {
currentState = std::move (newState);
}
State* getState () const { return currentState.get (); }
int getCount () const { return count; }
void setCount (int c) { count = c; }
void insertCoin () { currentState->insertCoin (this ); }
void ejectCoin () { currentState->ejectCoin (this ); }
void turnCrank () { currentState->turnCrank (this ); }
void dispense () { currentState->dispense (this ); }
void releaseBall () {
std::cout << "A gumball comes rolling out the slot" << std::endl;
if (count > 0 ) {
count--;
}
}
};
class NoCoinState : public State {
public :
void insertCoin (Context* context) override ;
void ejectCoin (Context* context) override ;
void turnCrank (Context* context) override ;
void dispense (Context* context) override ;
std::string getName () const override { return "NoCoinState" ; }
};
class HasCoinState : public State {
public :
void insertCoin (Context* context) override ;
void ejectCoin (Context* context) override ;
void turnCrank (Context* context) override ;
void dispense (Context* context) override ;
std::string getName () const override { return "HasCoinState" ; }
};
class SoldState : public State {
public :
void insertCoin (Context* context) override ;
void ejectCoin (Context* context) override ;
void turnCrank (Context* context) override ;
void dispense (Context* context) override ;
std::string getName () const override { return "SoldState" ; }
};
class SoldOutState : public State {
public :
void insertCoin (Context* context) override ;
void ejectCoin (Context* context) override ;
void turnCrank (Context* context) override ;
void dispense (Context* context) override ;
std::string getName () const override { return "SoldOutState" ; }
};
void NoCoinState::insertCoin (Context* context) {
std::cout << "You inserted a coin" << std::endl;
context->setState (std::make_unique <HasCoinState>());
}
void NoCoinState::ejectCoin (Context* context) {
std::cout << "You haven't inserted a coin" << std::endl;
}
void NoCoinState::turnCrank (Context* context) {
std::cout << "You turned, but there's no coin" << std::endl;
}
void NoCoinState::dispense (Context* context) {
std::cout << "You need to pay first" << std::endl;
}
void HasCoinState::insertCoin (Context* context) {
std::cout << "You can't insert another coin" << std::endl;
}
void HasCoinState::ejectCoin (Context* context) {
std::cout << "Coin returned" << std::endl;
context->setState (std::make_unique <NoCoinState>());
}
void HasCoinState::turnCrank (Context* context) {
std::cout << "You turned..." << std::endl;
context->setState (std::make_unique <SoldState>());
}
void HasCoinState::dispense (Context* context) {
std::cout << "No gumball dispensed" << std::endl;
}
void SoldState::insertCoin (Context* context) {
std::cout << "Please wait, we're already giving you a gumball" << std::endl;
}
void SoldState::ejectCoin (Context* context) {
std::cout << "Sorry, you already turned the crank" << std::endl;
}
void SoldState::turnCrank (Context* context) {
std::cout << "Turning twice doesn't get you another gumball" << std::endl;
}
void SoldState::dispense (Context* context) {
context->releaseBall ();
if (context->getCount () > 0 ) {
context->setState (std::make_unique <NoCoinState>());
} else {
context->setState (std::make_unique <SoldOutState>());
}
}
void SoldOutState::insertCoin (Context* context) {
std::cout << "You can't insert a coin, the machine is sold out" << std::endl;
}
void SoldOutState::ejectCoin (Context* context) {
std::cout << "You can't eject, you haven't inserted a coin yet" << std::endl;
}
void SoldOutState::turnCrank (Context* context) {
std::cout << "You turned, but there are no gumballs" << std::endl;
}
void SoldOutState::dispense (Context* context) {
std::cout << "No gumball dispensed" << std::endl;
}
void stateExample () {
Context gumballMachine (std::make_unique<NoCoinState>()) ;
gumballMachine.setCount (5 );
std::cout << "Current state: " << gumballMachine.getState ()->getName () << std::endl;
gumballMachine.insertCoin ();
std::cout << "Current state: " << gumballMachine.getState ()->getName () << std::endl;
gumballMachine.turnCrank ();
std::cout << "Current state: " << gumballMachine.getState ()->getName () << std::endl;
gumballMachine.insertCoin ();
gumballMachine.ejectCoin ();
std::cout << "Current state: " << gumballMachine.getState ()->getName () << std::endl;
}
为其他对象提供代理以控制访问。主题接口定义公共接口,真实主题实现业务逻辑,代理控制访问。
#include <iostream>
#include <string>
#include <memory>
class Image {
public :
virtual ~Image () = default ;
virtual void display () = 0 ;
};
class RealImage : public Image {
private :
std::string fileName;
void loadFromDisk () {
std::cout << "Loading " << fileName << " from disk" << std::endl;
}
public :
RealImage (const std::string& file) : fileName (file) {
loadFromDisk ();
}
void display () override {
std::cout << "Displaying " << fileName << std::endl;
}
};
class ProxyImage : public Image {
private :
std::unique_ptr<RealImage> realImage;
std::string fileName;
public :
ProxyImage (const std::string& file) : fileName (file) {}
void display () override {
if (!realImage) {
realImage = std::make_unique <RealImage>(fileName);
}
realImage->display ();
}
};
void proxyExample () {
std::cout << "Creating proxy images..." << std::endl;
Image* image1 = new ProxyImage ("image1.jpg" );
Image* image2 = new ProxyImage ("image2.jpg" );
std::cout << "Images created, but not loaded yet" << std::endl;
std::cout << "\nFirst display:" << std::endl;
image1->display ();
std::cout << "\nSecond display:" << std::endl;
image1->display ();
std::cout << "\nDisplaying second image:" << std::endl;
image2->display ();
delete image1;
delete image2;
}
class InternetAccess {
public :
virtual ~InternetAccess () = default ;
virtual void connectTo (const std::string& serverHost) = 0 ;
};
class RealInternetAccess : public InternetAccess {
public :
void connectTo (const std::string& serverHost) override {
std::cout << "Connecting to " << serverHost << std::endl;
}
};
class ProxyInternetAccess : public InternetAccess {
private :
std::unique_ptr<RealInternetAccess> realInternet;
std::string username;
bool isAccessAllowed () const {
return username == "admin" || username == "user" ;
}
public :
ProxyInternetAccess (const std::string& user) : username (user) {}
void connectTo (const std::string& serverHost) override {
if (!isAccessAllowed ()) {
std::cout << "Access denied for user: " << username << std::endl;
return ;
}
if (!realInternet) {
realInternet = std::make_unique <RealInternetAccess>();
}
realInternet->connectTo (serverHost);
}
};
void protectionProxyExample () {
InternetAccess* adminAccess = new ProxyInternetAccess ("admin" );
InternetAccess* guestAccess = new ProxyInternetAccess ("guest" );
adminAccess->connectTo ("google.com" );
guestAccess->connectTo ("google.com" );
delete adminAccess;
delete guestAccess;
}
架构设计 SOLID 是面向对象设计的五个基本原则:单一职责、开闭、里氏替换、接口隔离、依赖倒置。
S - 单一职责原则 (SRP)
一个类应该只有一个引起变化的原因,每个类只负责一个功能。
class User {
public :
void saveToDatabase () { }
void validateEmail () { }
void sendEmail () { }
};
class UserRepository {
public :
void save (const User& user) { }
};
class EmailValidator {
public :
bool isValid (const std::string& email) { }
};
class EmailService {
public :
void send (const std::string& to, const std::string& message) { }
};
O - 开闭原则 (OCP)
对扩展开放,对修改关闭。通过继承和组合实现扩展。
class AreaCalculator {
public :
double calculate (const std::string& shape, double width, double height) {
if (shape == "rectangle" ) return width * height;
if (shape == "circle" ) return 3.14 * width * width;
return 0 ;
}
};
class Shape {
public :
virtual ~Shape () = default ;
virtual double area () const = 0 ;
};
class Rectangle : public Shape {
private :
double width, height;
public :
Rectangle (double w, double h) : width (w), height (h) {}
double area () const override { return width * height; }
};
class Circle : public Shape {
private :
double radius;
public :
Circle (double r) : radius (r) {}
double area () const override { return 3.14 * radius * radius; }
};
L - 里氏替换原则 (LSP)
子类必须能够替换其基类,子类不应破坏基类的约定。
class Bird {
public :
virtual void fly () {
std::cout << "Flying" << std::endl;
}
};
class Penguin : public Bird {
public :
void fly () override {
throw std::runtime_error ("Penguins can't fly" );
}
};
class Bird {
public :
virtual ~Bird () = default ;
virtual void makeSound () = 0 ;
};
class FlyingBird : public Bird {
public :
void fly () {
std::cout << "Flying" << std::endl;
}
};
class Penguin : public Bird {
public :
void makeSound () override {
std::cout << "Squawk" << std::endl;
}
};
I - 接口隔离原则 (ISP)
客户端不应依赖它不需要的接口,将大接口拆分为小接口。
class Worker {
public :
virtual void work () = 0 ;
virtual void eat () = 0 ;
virtual void sleep () = 0 ;
};
class Robot : public Worker {
public :
void work () override { }
void eat () override { }
void sleep () override { }
};
class Workable {
public :
virtual ~Workable () = default ;
virtual void work () = 0 ;
};
class Eatable {
public :
virtual ~Eatable () = default ;
virtual void eat () = 0 ;
};
class Human : public Workable, public Eatable {
public :
void work () override { }
void eat () override { }
};
class Robot : public Workable {
public :
void work () override { }
};
D - 依赖倒置原则 (DIP)
高层模块不应依赖低层模块,都应依赖抽象。抽象不应依赖细节,细节应依赖抽象。
class LightBulb {
public :
void turnOn () {
std::cout << "LightBulb on" << std::endl;
}
};
class Switch {
private :
LightBulb bulb;
public :
Switch () : bulb () {}
void press () {
bulb.turnOn ();
}
};
class Switchable {
public :
virtual ~Switchable () = default ;
virtual void turnOn () = 0 ;
virtual void turnOff () = 0 ;
};
class LightBulb : public Switchable {
public :
void turnOn () override {
std::cout << "LightBulb on" << std::endl;
}
void turnOff () override {
std::cout << "LightBulb off" << std::endl;
}
};
class Fan : public Switchable {
public :
void turnOn () override {
std::cout << "Fan on" << std::endl;
}
void turnOff () override {
std::cout << "Fan off" << std::endl;
}
};
class Switch {
private :
Switchable& device;
public :
Switch (Switchable& d) : device (d) {}
void press () {
device.turnOn ();
}
};
将依赖关系外部注入。构造函数注入、Setter 注入、接口注入。
#include <memory>
#include <iostream>
#include <string>
class ILogger {
public :
virtual ~ILogger () = default ;
virtual void log (const std::string& message) = 0 ;
};
class IDatabase {
public :
virtual ~IDatabase () = default ;
virtual void save (const std::string& data) = 0 ;
};
class ConsoleLogger : public ILogger {
public :
void log (const std::string& message) override {
std::cout << "LOG: " << message << std::endl;
}
};
class FileLogger : public ILogger {
public :
void log (const std::string& message) override {
std::cout << "FILE LOG: " << message << std::endl;
}
};
class SQLDatabase : public IDatabase {
public :
void save (const std::string& data) override {
std::cout << "Saving to SQL: " << data << std::endl;
}
};
class NoSQLDatabase : public IDatabase {
public :
void save (const std::string& data) override {
std::cout << "Saving to NoSQL: " << data << std::endl;
}
};
class UserService {
private :
std::shared_ptr<ILogger> logger;
std::shared_ptr<IDatabase> database;
public :
UserService (std::shared_ptr<ILogger> log, std::shared_ptr<IDatabase> db)
: logger (log), database (db) {}
void setLogger (std::shared_ptr<ILogger> log) { logger = log; }
void setDatabase (std::shared_ptr<IDatabase> db) { database = db; }
void createUser (const std::string& userData) {
logger->log ("Creating user: " + userData);
database->save (userData);
logger->log ("User created successfully" );
}
};
class DIContainer {
private :
std::map<std::string, std::shared_ptr<void >> services;
public :
template <typename Interface, typename Implementation>
void registerService () {
services[typeid (Interface).name ()] = std::make_shared <Implementation>();
}
template <typename T>
std::shared_ptr<T> resolve () {
auto it = services.find (typeid (T).name ());
if (it != services.end ()) {
return std::static_pointer_cast <T>(it->second);
}
return nullptr ;
}
};
void dependencyInjectionExample () {
auto logger = std::make_shared <ConsoleLogger>();
auto database = std::make_shared <SQLDatabase>();
UserService userService (logger, database) ;
userService.createUser ("John Doe" );
DIContainer container;
container.registerService <ILogger, FileLogger>();
container.registerService <IDatabase, NoSQLDatabase>();
auto logger2 = container.resolve <ILogger>();
auto database2 = container.resolve <IDatabase>();
if (logger2 && database2) {
UserService userService2 (logger2, database2) ;
userService2. createUser ("Jane Smith" );
}
}
良好的代码组织和模块化。分层架构(表示层、业务层、数据层),模块划分按功能职责,接口设计清晰的模块边界。
namespace DataAccess {
class IRepository {
public :
virtual ~IRepository () = default ;
virtual void save (const std::string& data) = 0 ;
virtual std::string load (int id) = 0 ;
};
class UserRepository : public IRepository {
public :
void save (const std::string& data) override {
std::cout << "Saving user to database: " << data << std::endl;
}
std::string load (int id) override {
return "User data for ID: " + std::to_string (id);
}
};
}
namespace BusinessLogic {
class UserService {
private :
std::shared_ptr<DataAccess::IRepository> repository;
public :
UserService (std::shared_ptr<DataAccess::IRepository> repo) : repository (repo) {}
bool createUser (const std::string& userData) {
if (userData.empty ()) return false ;
repository->save (userData);
return true ;
}
std::string getUser (int id) {
return repository->load (id);
}
};
class ValidationService {
public :
bool validateEmail (const std::string& email) {
return email.find ('@' ) != std::string::npos;
}
bool validatePassword (const std::string& password) {
return password.length () >= 8 ;
}
};
}
namespace Presentation {
class UserController {
private :
std::shared_ptr<BusinessLogic::UserService> userService;
std::shared_ptr<BusinessLogic::ValidationService> validationService;
public :
UserController (
std::shared_ptr<BusinessLogic::UserService> userSvc,
std::shared_ptr<BusinessLogic::ValidationService> validationSvc)
: userService (userSvc), validationService (validationSvc) {}
void registerUser (const std::string& email, const std::string& password) {
if (!validationService->validateEmail (email)) {
std::cout << "Invalid email format" << std::endl;
return ;
}
if (!validationService->validatePassword (password)) {
std::cout << "Password too short" << std::endl;
return ;
}
std::string userData = "Email: " + email + ", Password: " + password;
if (userService->createUser (userData)) {
std::cout << "User registered successfully" << std::endl;
} else {
std::cout << "Failed to register user" << std::endl;
}
}
};
}
void modularExample () {
auto repository = std::make_shared <DataAccess::UserRepository>();
auto userService = std::make_shared <BusinessLogic::UserService>(repository);
auto validationService = std::make_shared <BusinessLogic::ValidationService>();
auto userController = std::make_shared <Presentation::UserController>(
userService, validationService);
userController->registerUser ("[email protected] " , "password123" );
userController->registerUser ("invalid-email" , "short" );
}
TDD 开发流程:编写测试(先写失败的测试)、运行测试(确认失败)、编写代码(最小化代码使测试通过)、重构(优化代码保持测试通过)。
#define ASSERT_TRUE(condition) \nif (!(condition)) { \n std::cout << "FAIL: " << #condition << " at line " << __LINE__ << std::endl; \n} else { \n std::cout << "PASS: " << #condition << std::endl; \n}
#define ASSERT_EQ(expected, actual) \nif ((expected) != (actual)) { \n std::cout << "FAIL: expected " << (expected) << " but got " << (actual) << " at line " << __LINE__ << std::endl; \n} else { \n std::cout << "PASS: " << (expected) << " == " << (actual) << std::endl; \n}
class Calculator {
public :
int add (int a, int b) { return a + b; }
int subtract (int a, int b) { return a - b; }
int multiply (int a, int b) { return a * b; }
double divide (int a, int b) {
if (b == 0 ) throw std::runtime_error ("Division by zero" );
return static_cast <double >(a) / b;
}
};
void testCalculator () {
Calculator calc;
ASSERT_EQ (5 , calc.add (2 , 3 ));
ASSERT_EQ (0 , calc.add (-2 , 2 ));
ASSERT_EQ (-5 , calc.add (-2 , -3 ));
ASSERT_EQ (1 , calc.subtract (3 , 2 ));
ASSERT_EQ (-1 , calc.subtract (2 , 3 ));
ASSERT_EQ (6 , calc.multiply (2 , 3 ));
ASSERT_EQ (0 , calc.multiply (2 , 0 ));
ASSERT_EQ (2.0 , calc.divide (4 , 2 ));
ASSERT_EQ (1.5 , calc.divide (3 , 2 ));
try {
calc.divide (1 , 0 );
ASSERT_TRUE (false );
} catch (const std::runtime_error&) {
ASSERT_TRUE (true );
}
}
class Stack {
private :
std::vector<int > data;
public :
void push (int item) { data.push_back (item); }
int pop () {
if (data.empty ()) {
throw std::runtime_error ("Stack is empty" );
}
int item = data.back ();
data.pop_back ();
return item;
}
bool isEmpty () const { return data.empty (); }
int size () const { return data.size (); }
};
void testStack () {
Stack stack;
ASSERT_TRUE (stack.isEmpty ());
ASSERT_EQ (0 , stack.size ());
stack.push (1 );
ASSERT_FALSE (stack.isEmpty ());
ASSERT_EQ (1 , stack.size ());
stack.push (2 );
ASSERT_EQ (2 , stack.size ());
ASSERT_EQ (2 , stack.pop ());
ASSERT_EQ (1 , stack.size ());
ASSERT_EQ (1 , stack.pop ());
ASSERT_TRUE (stack.isEmpty ());
try {
stack.pop ();
ASSERT_TRUE (false );
} catch (const std::runtime_error&) {
ASSERT_TRUE (true );
}
}
void runTests () {
std::cout << "=== Calculator Tests ===" << std::endl;
testCalculator ();
std::cout << "\n=== Stack Tests ===" << std::endl;
testStack ();
}
使用一致的命名约定
保持函数和类的职责单一
添加适当的注释和文档
遵循项目编码规范
优先使用智能指针
遵循 RAII 原则
避免内存泄漏和野指针
合理使用移动语义
选择合适的容器和算法
避免不必要的拷贝
使用编译期优化
进行性能分析
使用异常处理错误情况
提供清晰的错误信息
保证异常安全
合理使用 noexcept
使用 auto 简化代码
利用范围 for 循环
使用 lambda 表达式
采用智能指针管理资源
遵循 SOLID 原则
使用设计模式解决常见问题
保持代码的可测试性
考虑代码的可维护性
class ModernCppExample {
private :
std::unique_ptr<int []> data_;
size_t size_;
public :
ModernCppExample (size_t size) : size_ (size) {
data_ = std::make_unique <int []>(size_);
std::fill_n (data_.get (), size_, 0 );
}
ModernCppExample (const ModernCppExample&) = delete ;
ModernCppExample& operator =(const ModernCppExample&) = delete ;
ModernCppExample (ModernCppExample&&) = default ;
ModernCppExample& operator =(ModernCppExample&&) = default ;
size_t size () const noexcept { return size_; }
int * begin () { return data_.get (); }
int * end () { return data_.get () + size_; }
const int * begin () const { return data_.get (); }
const int * end () const { return data_.get () + size_; }
void at (size_t index, int value) {
if (index >= size_) {
throw std::out_of_range ("Index out of range" );
}
data_[index] = value;
}
constexpr static size_t max_size () noexcept { return 1000000 ; }
};
void bestPracticeExample () {
try {
ModernCppExample example (10 ) ;
for (auto & item : example) {
item = 42 ;
}
std::sort (example.begin (), example.end ());
std::cout << "Size: " << example.size () << std::endl;
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what () << std::endl;
}
}
总结 这 100 道 C++ 面试题涵盖了现代 C++ 开发的核心知识点:
核心技能
基础语法 :面向对象、继承多态、运算符重载
现代特性 :智能指针、lambda、移动语义、并发编程
STL 精通 :容器、算法、迭代器、函数对象
设计模式 :常用模式的理解和应用
进阶能力
内存管理 :RAII、智能指针、异常安全
性能优化 :移动语义、编译期优化、缓存友好
并发编程 :线程、互斥锁、原子操作、异步编程
架构设计 :SOLID 原则、依赖注入、模块化
面试准备建议
理解原理 :不要死记硬背,理解底层机制
动手实践 :多写代码,积累实际经验
关注现代 C++ :掌握 C++11/14/17/20 新特性
项目经验 :结合实际项目理解概念
持续学习 :C++ 标准不断更新,保持学习
相关免费在线工具 加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
Gemini 图片去水印 基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online