C++经典面试题100道

C++经典面试题100道

📋 目录提纲

🎯 第一部分:C++基础语法 (1-25题)

  • 面向对象基础 (1-8):类、对象、构造函数、析构函数
  • 访问控制与封装 (9-13):public/private/protected、友元
  • 继承与多态 (14-20):继承方式、虚函数、纯虚函数、抽象类
  • 运算符重载 (21-25):重载规则、常用运算符重载

🔧 第二部分:C++核心特性 (26-50题)

  • 模板编程 (26-32):函数模板、类模板、模板特化
  • STL容器 (33-40):vector、list、map、set等容器特性
  • STL算法 (41-45):sort、find、transform等常用算法
  • 智能指针 (46-50):unique_ptr、shared_ptr、weak_ptr

⚡ 第三部分:内存管理与性能 (51-70题)

  • 内存管理 (51-58):new/delete、内存布局、对象生命周期
  • 异常处理 (59-63):try-catch、异常安全、RAII
  • 性能优化 (64-70):移动语义、完美转发、编译优化

🏗️ 第四部分:高级特性 (71-85题)

  • 多线程编程 (71-77):thread、mutex、condition_variable、atomic
  • 现代C++特性 (78-85):auto、lambda、constexpr、智能指针

🎨 第五部分:设计模式与架构 (86-100题)

  • 设计模式 (86-95):单例、工厂、观察者等常用模式
  • 架构设计 (96-100):SOLID原则、代码组织、最佳实践

🎯 第一部分:C++基础语法 (1-25题)

📚 面向对象基础 (1-8)

1. 什么是面向对象编程?C++中如何体现?

答案:
面向对象编程(OOP)是一种编程范式,通过对象来组织代码。C++中的体现:

  • 封装:将数据和操作数据的方法封装在类中
  • 继承:子类继承父类的属性和方法
  • 多态:同一接口的不同实现
class Animal {
public:
    virtual void makeSound() = 0;  // 纯虚函数
};

class Dog : public Animal {
public:
    void makeSound() override { cout << "Woof!" << endl; }
};
2. 类和结构的区别?

答案:
主要区别在于默认访问权限:

  • class:默认private访问权限
  • struct:默认public访问权限
class MyClass {
    int x;  // private
};

struct MyStruct {
    int x;  // public
};
3. 构造函数的作用和种类?

答案:
构造函数用于初始化对象,种类包括:

  • 默认构造函数:无参数
  • 参数化构造函数:带参数
  • 拷贝构造函数:同类型对象初始化
  • 移动构造函数:C++11,资源转移
class Example {
public:
    Example() {}                    // 默认构造
    Example(int x) : val(x) {}      // 参数化构造
    Example(const Example& other) : val(other.val) {}  // 拷贝构造
    Example(Example&& other) noexcept : val(other.val) {}  // 移动构造
private:
    int val;
};
4. 析构函数的作用?什么时候调用?

答案:
析构函数用于清理对象资源,调用时机:

  • 对象生命周期结束时
  • delete动态分配的对象时
  • 程序正常结束时(全局/静态对象)
class Resource {
public:
    Resource() { data = new int[100]; }
    ~Resource() { delete[] data; }  // 释放资源
private:
    int* data;
};
5. 什么是拷贝构造函数?为什么要自己实现?

答案:
拷贝构造函数用同类型对象初始化新对象。需要自己实现的情况:

  • 类包含指针成员
  • 需要深拷贝而非浅拷贝
  • 需要特殊的拷贝逻辑
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;
};
6. 什么是移动构造函数?有什么优势?

答案:
移动构造函数(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;
};
7. 初始化列表的作用和优势?

答案:
初始化列表用于初始化类成员,优势:

  • 效率更高:直接初始化而非先默认构造再赋值
  • 必须使用:const成员、引用成员、没有默认构造函数的成员
  • 顺序保证:按成员声明顺序初始化
class Person {
public:
    Person(const string& name, int age) 
        : name_(name), age_(age) {  // 初始化列表
        // 构造函数体
    }
private:
    string name_;
    int age_;
};
8. this指针的作用?

答案:
this指针指向当前对象,用于:

  • 区分成员变量和参数
  • 返回当前对象的引用
  • 在成员函数中访问对象
class Student {
public:
    Student& setName(const string& name) {
        this->name = name;  // 区分成员变量
        return *this;       // 返回当前对象引用
    }
private:
    string name;
};

🔐 访问控制与封装 (9-13)

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;    // OK:公有成员
        prot = 2;   // OK:保护成员,派生类可访问
        // priv = 3; // Error:私有成员,派生类不可访问
    }
};
10. 友元函数和友元类的作用?

答案:
友元可以访问类的私有和保护成员:

  • 友元函数:非成员函数可访问私有成员
  • 友元类:另一个类的所有成员函数都可访问私有成员
class Box {
    friend void printBox(const Box& box);  // 友元函数
    friend class BoxPrinter;               // 友元类
    
private:
    int width, height;
};

void printBox(const Box& box) {
    cout << box.width << "x" << box.height;  // 可访问私有成员
}
11. 什么是封装?为什么重要?

答案:
封装是将数据和操作数据的方法绑定在一起,隐藏内部实现:

  • 数据保护:防止外部直接修改数据
  • 接口清晰:只暴露必要的操作
  • 易于维护:内部实现改变不影响外部代码
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;  // 封装数据
};
12. const成员函数的作用?

答案:
const成员函数承诺不修改对象状态:

  • 可以被const对象调用
  • 不能修改非mutable成员变量
  • 提高代码安全性和可读性
class Rectangle {
public:
    double getArea() const {  // const成员函数
        return width * height;  // 只读操作
    }
    
    void setWidth(double w) { width = w; }  // 非const函数
private:
    double width, height;
};
13. mutable关键字的作用?

答案:
mutable允许在const成员函数中修改成员变量:

  • 用于需要在逻辑上保持const但需要修改的成员
  • 常用于缓存、计数器等
class Calculator {
public:
    int getResult() const {
        cache_count++;  // mutable成员可在const函数中修改
        return compute();
    }
private:
    mutable int cache_count = 0;  // mutable成员
    int compute() const { return 42; }
};

🧬 继承与多态 (14-20)

14. 继承的方式有哪些?区别是什么?

答案:
C++有三种继承方式:

  • public继承:基类public→派生类public,protected→protected
  • protected继承:基类public→派生类protected,protected→protected
  • private继承:基类public→派生类private,protected→private
class Base {
public:    int pub;
protected: int prot;
private:   int priv;
};

class PublicDerived : public Base {
    // pub保持public,prot保持protected,priv不可访问
};

class PrivateDerived : private Base {
    // pub和prot都变成private,priv不可访问
};
15. 什么是虚函数?作用是什么?

答案:
虚函数实现运行时多态:

  • 允许通过基类指针调用派生类的实现
  • 需要virtual关键字声明
  • 通过虚函数表实现
class Shape {
public:
    virtual double getArea() const = 0;  // 纯虚函数
    virtual void draw() const { cout << "Drawing shape" << endl; }
};

class Circle : public Shape {
public:
    double getArea() const override { return 3.14 * radius * radius; }
    void draw() const override { cout << "Drawing circle" << endl; }
private:
    double radius;
};
16. 纯虚函数和抽象类的概念?

答案:

  • 纯虚函数:没有实现的虚函数,= 0表示
  • 抽象类:包含纯虚函数的类,不能实例化
class Animal {  // 抽象类
public:
    virtual void makeSound() = 0;  // 纯虚函数
    virtual void eat() { cout << "Eating" << endl; }  // 普通虚函数
};

// Animal animal;  // Error:不能实例化抽象类
class Dog : public Animal {
public:
    void makeSound() override { cout << "Woof!" << endl; }  // 必须实现
};
17. 什么是虚函数表(vtable)?

答案:
虚函数表是实现多态的机制:

  • 每个有虚函数的类都有一个虚函数表
  • 对象中包含指向虚函数表的指针
  • 虚函数表存储虚函数的地址
// 编译器为这个类生成虚函数表
class Base {
public:
    virtual void func1() {}
    virtual void func2() {}
};

// 内存布局:[vptr][成员变量]
// vptr指向虚函数表:[&Base::func1, &Base::func2]
18. override关键字的作用?

答案:
override(C++11)明确表示重写基类虚函数:

  • 编译器检查是否真的重写了基类函数
  • 防止拼写错误或参数不匹配
  • 提高代码可读性
class Base {
public:
    virtual void process(int value) {}
};

class Derived : public Base {
public:
    void process(int value) override {  // 明确表示重写
        // 如果基类没有对应的虚函数,编译器会报错
    }
};
19. final关键字的作用?

答案:
final(C++11)用于阻止继承或重写:

  • 修饰类:不能被继承
  • 修饰虚函数:不能被重写
class FinalClass final {  // 不能被继承
public:
    virtual void method() final {  // 不能被重写
        // 实现
    }
};

// class Derived : public FinalClass {}  // Error:不能继承final类
20. 多重继承的问题和解决方案?

答案:
多重继承的问题:

  • 菱形继承:二义性
  • 数据冗余:基类成员重复

解决方案:

  • 虚继承:解决菱形继承问题
  • 明确作用域:使用类名限定
class Animal {
public:
    void eat() { cout << "Eating" << endl; }
};

class Mammal : virtual public Animal {};  // 虚继承
class Bird : virtual public Animal {};     // 虚继承

class Bat : public Mammal, public Bird {
public:
    void test() {
        eat();  // OK:没有二义性
    }
};

⚙️ 运算符重载 (21-25)

21. 运算符重载的规则和限制?

答案:
规则和限制:

  • 不能重载的运算符:. :: 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;
};
22. 前置++和后置++的区别?

答案:
区别在于参数和返回值:

  • 前置++:无参数,返回引用
  • 后置++:int参数(仅用于区分),返回值
class Counter {
public:
    // 前置++
    Counter& operator++() {
        ++value;
        return *this;  // 返回引用
    }
    
    // 后置++
    Counter operator++(int) {
        Counter temp = *this;
        ++value;  // 调用前置++
        return temp;  // 返回临时对象
    }
private:
    int value = 0;
};
23. 赋值运算符重载的注意事项?

答案:
注意事项:

  • 检查自赋值
  • 返回当前对象的引用
  • 正确处理资源
  • 考虑异常安全
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;
};
24. 下标运算符[]的重载?

答案:
下标运算符提供数组式访问:

  • 通常提供const和非const两个版本
  • 应该进行边界检查
  • 返回引用以支持修改
class Array {
public:
    int& operator[](size_t index) {
        if (index >= size) throw out_of_range("Index out of range");
        return data[index];
    }
    
    const int& operator[](size_t index) const {
        if (index >= size) throw out_of_range("Index out of range");
        return data[index];
    }
private:
    int* data;
    size_t size;
};
25. 函数调用运算符()的重载?

答案:
函数调用运算符使对象可以像函数一样调用:

  • 创建函数对象(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;
    }
};

// 使用
Adder add;
cout << add(3, 4) << endl;  // 输出7

Multiplier times3(3);
cout << times3(5) << endl;  // 输出15

🔧 第二部分:C++核心特性 (26-50题)

📝 模板编程 (26-32)

26. 什么是函数模板?

答案:
函数模板允许编写泛型函数,支持多种数据类型:

  • 使用template关键字声明
  • 类型参数用typename或class
  • 编译器自动生成具体类型的函数
template<typename T>
T max(T a, T b) {
    return (a > b) ? a : b;
}

// 使用
int i = max(3, 7);        // T = int
double d = max(3.14, 2.71); // T = double
27. 什么是类模板?

答案:
类模板定义泛型类,支持多种数据类型:

  • 成员函数在类外定义时需要模板声明
  • 可以有非类型模板参数
  • 支持模板特化
template<typename T>
class Stack {
private:
    vector<T> elements;
public:
    void push(const T& elem) {
        elements.push_back(elem);
    }
    
    T pop() {
        if (elements.empty()) {
            throw out_of_range("Stack<>::pop(): empty stack");
        }
        T elem = elements.back();
        elements.pop_back();
        return elem;
    }
};

// 使用
Stack<int> intStack;
Stack<string> stringStack;
28. 模板特化的概念和用法?

答案:
模板特化为特定类型提供定制实现:

  • 完全特化:所有模板参数都指定
  • 部分特化:部分模板参数指定(仅类模板)
// 通用模板
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; }
};
29. 模板参数的类型?

答案:
模板参数类型:

  • 类型参数: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) cout << "Setting index " << index << endl;
        data[index] = value;
    }
};

// 模板模板参数
template<typename T, template<typename, typename> class Container>
class Adapter {
private:
    Container<T, allocator<T>> container;
public:
    void add(const T& item) { container.push_back(item); }
};
30. SFINAE是什么?

答案:
SFINAE(Substitution Failure Is Not An Error):

  • 替换失败不是错误
  • 模板参数替换失败时,不会编译错误,而是寻找其他重载
  • 常用于模板元编程和类型萃取
template<typename T>
typename T::value_type test(typename T::iterator*);  // 如果T有iterator成员

template<typename>
int test(...);  // 匹配所有其他情况

template<typename T>
auto hasIterator(T t) -> decltype(test<T>(nullptr)) {
    return true;  // 有iterator
}

template<typename T>
int hasIterator(...) {
    return false;  // 没有iterator
}
31. 模板实例化的过程?

答案:
模板实例化过程:

  1. 编译期:遇到模板使用时生成具体代码
  2. 两阶段查找:模板定义时和实例化时
  3. 隐式实例化:使用时自动生成
  4. 显式实例化:明确指定类型
// 模板定义
template<typename T>
T square(T x) { return x * x; }

// 隐式实例化
int result1 = square(5);        // 实例化square<int>
double result2 = square(3.14);  // 实例化square<double>

// 显式实例化
template int square<int>(int);  // 显式实例化int版本
32. 模板的优缺点?

答案:
优点:

  • 代码复用:一套代码支持多种类型
  • 类型安全:编译期类型检查
  • 性能:与手写代码性能相同

缺点:

  • 编译时间长:每个使用都实例化
  • 代码膨胀:生成多个版本的代码
  • 调试困难:错误信息复杂
  • 编译器支持:老旧编译器支持有限

📦 STL容器 (33-40)

33. vector的特点和适用场景?

答案:
vector是动态数组:

  • 特点:连续内存、随机访问、自动扩容
  • 时间复杂度:访问O(1)、插入删除O(n)
  • 适用场景:频繁随机访问、尾部插入
vector<int> vec;
vec.push_back(1);    // 尾部插入
vec[0] = 10;         // 随机访问
vec.size();          // 元素个数
vec.capacity();      // 容量
vec.reserve(100);    // 预分配容量
34. list的特点和适用场景?

答案:
list是双向链表:

  • 特点:非连续内存、双向遍历、任意位置插入删除
  • 时间复杂度:访问O(n)、插入删除O(1)
  • 适用场景:频繁插入删除、不需要随机访问
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的区别?

答案:

特性mapunordered_map
底层结构红黑树哈希表
有序性有序无序
查找复杂度O(log n)O(1)平均
插入复杂度O(log n)O(1)平均
内存占用较小较大
// map - 有序
map<string, int> ordered_map;
ordered_map["apple"] = 1;
ordered_map["banana"] = 2;

// unordered_map - 无序但更快
unordered_map<string, int> unordered_map;
unordered_map["apple"] = 1;
unordered_map["banana"] = 2;
36. set和multiset的区别?

答案:

  • set:元素唯一、自动排序
  • multiset:元素可重复、自动排序
set<int> s;
s.insert(1);
s.insert(1);  // 重复插入失败
// s = {1}

multiset<int> ms;
ms.insert(1);
ms.insert(1);  // 重复插入成功
// ms = {1, 1}
37. deque的特点?

答案:
deque是双端队列:

  • 特点:两端插入删除高效、非严格连续内存
  • 时间复杂度:两端操作O(1)、中间操作O(n)
  • 适用场景:需要在两端频繁操作
deque<int> dq;
dq.push_front(1);   // 头部插入
dq.push_back(2);    // 尾部插入
dq.pop_front();     // 头部删除
dq.pop_back();      // 尾部删除
38. 容器的选择策略?

答案:
选择策略:

  • vector:需要随机访问、尾部操作
  • list:频繁中间插入删除
  • deque:两端频繁操作
  • map:需要键值对、有序
  • unordered_map:需要键值对、无序但快速
  • set:唯一元素、有序
  • priority_queue:需要优先级队列
39. 容器的emplace系列函数?

答案:
emplace系列直接构造元素,避免临时对象:

  • emplace:在指定位置构造
  • emplace_back:在尾部构造
  • emplace_front:在头部构造
vector<pair<int, string>> vec;

// 传统方式:构造临时对象
vec.push_back(make_pair(1, "hello"));

// emplace方式:直接构造
vec.emplace_back(1, "hello");  // 更高效
40. 容器的空间配置器?

答案:
空间配置器管理内存分配:

  • 默认allocator:使用new/delete
  • 自定义allocator:特殊内存管理需求
  • 内存池:提高分配效率
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);
    }
};

// 使用自定义分配器
vector<int, MyAllocator<int>> vec;

🔧 STL算法 (41-45)

41. sort算法的使用和注意事项?

答案:
sort是快速排序实现:

  • 时间复杂度:平均O(n log n),最坏O(n²)
  • 稳定性:不稳定排序
  • 自定义比较:可提供比较函数
vector<int> vec = {3, 1, 4, 1, 5};

// 默认升序
sort(vec.begin(), vec.end());

// 降序
sort(vec.begin(), vec.end(), greater<int>());

// 自定义比较
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),需要有序序列
vector<int> vec = {1, 3, 5, 7, 9};

// find - 线性搜索
auto it1 = find(vec.begin(), vec.end(), 5);

// binary_search - 二分搜索(需要先排序)
bool found = binary_search(vec.begin(), vec.end(), 5);

// lower_bound/upper_bound - 找范围
auto lower = lower_bound(vec.begin(), vec.end(), 5);
auto upper = upper_bound(vec.begin(), vec.end(), 5);
43. for_each和范围for循环的区别?

答案:

  • for_each:算法函数,可配合函数对象
  • 范围for:语言特性,更简洁
vector<int> vec = {1, 2, 3, 4, 5};

// for_each
for_each(vec.begin(), vec.end(), [](int& x) { x *= 2; });

// 范围for循环
for (int& x : vec) {
    x *= 2;
}
44. transform算法的使用?

答案:
transform对序列进行变换:

  • 一元变换:对每个元素应用函数
  • 二元变换:对两个序列对应元素应用函数
vector<int> src = {1, 2, 3, 4, 5};
vector<int> dest(src.size());

// 一元变换
transform(src.begin(), src.end(), dest.begin(), 
          [](int x) { return x * x; });

// 二元变换
vector<int> src2 = {5, 4, 3, 2, 1};
vector<int> dest2(src.size());
transform(src.begin(), src.end(), src2.begin(), dest2.begin(),
          [](int a, int b) { return a + b; });
45. remove和erase的区别?

答案:

  • remove:将不需要的元素移到末尾,返回新逻辑终点
  • erase:真正删除元素
vector<int> vec = {1, 2, 3, 4, 5, 3, 6};

// remove-erase惯用法
auto new_end = remove(vec.begin(), vec.end(), 3);  // 移动3到末尾
vec.erase(new_end, vec.end());  // 真正删除

// 一行完成
vec.erase(remove(vec.begin(), vec.end(), 3), vec.end());

🧠 智能指针 (46-50)

46. unique_ptr的特点和使用?

答案:
unique_ptr是独占所有权的智能指针:

  • 独占所有权:不能复制,只能移动
  • 自动释放:析构时自动delete
  • 轻量级:开销接近原始指针
unique_ptr<int> ptr1 = make_unique<int>(42);
// unique_ptr<int> ptr2 = ptr1;  // Error:不能复制
unique_ptr<int> ptr2 = move(ptr1);  // OK:移动

// 自定义删除器
unique_ptr<FILE, decltype(&fclose)> file(fopen("test.txt", "r"), fclose);
47. shared_ptr的特点和使用?

答案:
shared_ptr是共享所有权的智能指针:

  • 引用计数:多个指针共享对象
  • 线程安全:引用计数操作是原子的
  • 循环引用:可能导致内存泄漏
shared_ptr<int> ptr1 = make_shared<int>(42);
shared_ptr<int> ptr2 = ptr1;  // 引用计数+1

cout << ptr1.use_count() << endl;  // 输出2

ptr2.reset();  // 引用计数-1
cout << ptr1.use_count() << endl;  // 输出1
48. weak_ptr的作用?

答案:
weak_ptr解决shared_ptr的循环引用问题:

  • 弱引用:不影响引用计数
  • 观察者:观察shared_ptr管理的对象
  • lock():尝试获取shared_ptr
class Node {
public:
    shared_ptr<Node> next;
    weak_ptr<Node> prev;  // 使用weak_ptr避免循环引用
};

shared_ptr<Node> node1 = make_shared<Node>();
shared_ptr<Node> node2 = make_shared<Node>();

node1->next = node2;
node2->prev = node1;  // weak_ptr不增加引用计数
49. make_shared和make_unique的优势?

答案:
优势:

  • 异常安全:避免内存泄漏
  • 性能更好:一次内存分配
  • 代码简洁:更易读
// 传统方式
shared_ptr<int> ptr(new int(42));  // 两次分配:对象+控制块

// make_shared方式
auto ptr = make_shared<int>(42);   // 一次分配:对象+控制块一起
50. 智能指针的选择策略?

答案:
选择策略:

  • unique_ptr:独占所有权,最轻量
  • shared_ptr:需要共享所有权
  • weak_ptr:解决循环引用,观察者模式
  • 原始指针:不拥有所有权,仅观察
// 选择指南
class Owner {
    unique_ptr<Resource> resource;  // 独占资源
};

class Observer {
    weak_ptr<Subject> subject;      // 观察主题
};

class Collaborator {
    shared_ptr<Data> data;          // 协作数据
};

⚡ 第三部分:内存管理与性能 (51-70题)

💾 内存管理 (51-58)

51. new和malloc的区别?

答案:

特性newmalloc
类型安全安全不安全
构造函数调用不调用
析构函数delete调用free不调用
大小计算自动手动
失败处理抛出异常返回NULL
重载可重载不可重载
// new - 类型安全,调用构造函数
MyClass* obj1 = new MyClass();

// malloc - 不安全,不调用构造函数
MyClass* obj2 = (MyClass*)malloc(sizeof(MyClass));

// 对应的释放
delete obj1;     // 调用析构函数
free(obj2);       // 不调用析构函数
52. delete和free的区别?

答案:

  • 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);  // 错误
53. 对象的内存布局?

答案:
对象内存布局:

  • 虚函数表指针:有虚函数时存在
  • 成员变量:按声明顺序排列
  • 内存对齐:按对齐要求填充
  • 继承:基类成员在前
class Base {
public:
    virtual void func() {}
    int a;
    char b;
};

class Derived : public Base {
public:
    void func() override {}
    int c;
};

// Derived内存布局:
// [vptr][a][padding][b][padding][c]
54. 内存对齐的概念和作用?

答案:
内存对齐是数据存储在特定地址边界:

  • 作用:提高CPU访问效率
  • 规则:按成员最大对齐值对齐
  • 控制:使用alignas指定对齐
struct Example {
    char a;      // 1字节
    // 3字节填充
    int b;       // 4字节对齐
    char c;      // 1字节
    // 3字节填充
};  // 总大小12字节

// 控制对齐
struct alignas(16) Aligned {
    int data[4];
};  // 强制16字节对齐
55. RAII是什么?

答案:
RAII(Resource Acquisition Is Initialization):

  • 资源获取即初始化
  • 构造函数获取资源,析构函数释放资源
  • 异常安全:即使异常也能正确释放
  • 智能指针:RAII的典型应用
class FileHandler {
public:
    FileHandler(const char* filename) {
        file = fopen(filename, "r");
        if (!file) throw runtime_error("Cannot open file");
    }
    
    ~FileHandler() {
        if (file) fclose(file);  // 自动释放
    }
    
    FILE* get() { return file; }
private:
    FILE* file;
};

// 使用
{
    FileHandler fh("test.txt");  // 获取资源
    // 使用文件...
}  // 自动释放资源
56. 对象的生命周期?

答案:
对象生命周期阶段:

  1. 分配:获取内存
  2. 初始化:调用构造函数
  3. 使用:对象可用状态
  4. 销毁:调用析构函数
  5. 释放:内存回收
class Lifecycle {
public:
    Lifecycle() { cout << "构造" << endl; }
    ~Lifecycle() { cout << "析构" << endl; }
};

// 不同存储期的对象
Lifecycle global_obj;        // 静态存储期,程序结束时销毁

void func() {
    static Lifecycle static_obj;  // 静态存储期,程序结束时销毁
    Lifecycle local_obj;          // 自动存储期,函数结束时销毁
    auto* dynamic_obj = new Lifecycle();  // 动态存储期,delete时销毁
    delete dynamic_obj;
}
57. 内存泄漏的检测和预防?

答案:
检测方法:

  • Valgrind:Linux下内存检测工具
  • AddressSanitizer:编译器内置检测
  • 智能指针:自动管理内存
  • 代码审查:人工检查

预防策略:

  • RAII:资源自动管理
  • 智能指针:避免手动delete
  • 代码规范:明确的内存管理规则
// 使用智能指针预防泄漏
class ResourceManager {
public:
    void addResource(shared_ptr<Resource> resource) {
        resources.push_back(resource);
    }
private:
    vector<shared_ptr<Resource>> resources;
};
58. 自定义内存管理?

答案:
自定义内存管理场景:

  • 性能优化:减少分配开销
  • 特殊需求:固定大小块、内存池
  • 调试目的:跟踪内存使用
class MemoryPool {
private:
    struct Block {
        Block* next;
    };
    
    Block* freeList = nullptr;
    size_t blockSize;
    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;
    }
};

⚠️ 异常处理 (59-63)

59. C++异常处理机制?

答案:
异常处理三要素:

  • try:可能抛出异常的代码块
  • catch:捕获并处理异常
  • throw:抛出异常
try {
    // 可能抛出异常的代码
    if (error) {
        throw runtime_error("Something went wrong");
    }
} catch (const runtime_error& e) {
    cout << "捕获异常: " << e.what() << endl;
} catch (...) {
    cout << "捕获未知异常" << endl;
}
60. 异常安全的级别?

答案:
异常安全三个级别:

  • 基本保证:无资源泄漏,对象状态有效
  • 强保证:操作成功或回滚到原状态
  • 不抛异常保证:noexcept,绝不抛出异常
// 基本保证
void basicGuarantee() {
    auto* ptr = new int[100];
    try {
        // 可能抛出异常的操作
        process(ptr);
    } catch (...) {
        delete[] ptr;  // 确保资源释放
        throw;         // 重新抛出
    }
    delete[] ptr;
}

// 强保证
void strongGuarantee(vector<int>& vec) {
    vector<int> backup = vec;  // 备份
    try {
        // 修改操作
        modify(vec);
    } catch (...) {
        vec = backup;  // 回滚
        throw;
    }
}

// 不抛异常保证
void noThrowGuarantee() noexcept {
    // 绝不抛出异常的代码
}
61. noexcept的作用?

答案:
noexcept指定函数不抛出异常:

  • 性能优化:编译器可以生成更优代码
  • 程序终止:抛出异常时直接terminate
  • 移动语义:移动操作通常标记noexcept
// noexcept函数
void safeFunction() noexcept {
    // 如果抛出异常,程序会调用terminate()
}

// 条件noexcept
template<typename T>
void moveIfNoexcept(T& src, T& dest) noexcept(noexcept(T(move(src)))) {
    dest = move(src);
}

// 移动构造函数通常标记noexcept
class MyClass {
public:
    MyClass(MyClass&& other) noexcept : data(move(other.data)) {}
private:
    vector<int> data;
};
62. 异常和错误码的比较?

答案:

特性异常错误码
性能较高开销低开销
可读性清晰分离混合逻辑
强制性强制处理可忽略
信息量丰富有限
适用场景异常情况预期错误
// 异常方式
int divide(int a, int b) {
    if (b == 0) {
        throw 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;
}
63. RAII在异常处理中的作用?

答案:
RAII确保异常安全:

  • 自动清理:析构函数自动调用
  • 资源管理:智能指针、文件句柄等
  • 异常传播:资源正确释放
class ExceptionSafe {
public:
    ExceptionSafe() {
        resource1 = acquireResource1();
        resource2 = acquireResource2();  // 可能抛出异常
        // 如果resource2获取失败,resource1会自动释放
    }
    
    ~ExceptionSafe() {
        releaseResource2(resource2);
        releaseResource1(resource1);
    }
private:
    Resource* resource1;
    Resource* resource2;
};

🚀 性能优化 (64-70)

64. 移动语义的概念和优势?

答案:
移动语义转移资源而非拷贝:

  • 避免深拷贝:直接转移资源所有权
  • 提高性能:特别是大对象
  • 右值引用:绑定到临时对象
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 = move(s1);   // 移动构造
String s4 = String("World");  // 移动构造(临时对象)
65. 完美转发的概念?

答案:
完美转发保持参数的值类别:

  • 转发引用:template T&&
  • forward函数:保持左值/右值特性
  • 通用引用:可以绑定左值和右值
template<typename T>
void wrapper(T&& arg) {
    // 完美转发arg到func
    func(forward<T>(arg));
}

void func(int& x) { cout << "左值引用" << endl; }
void func(int&& x) { cout << "右值引用" << endl; }

int a = 10;
wrapper(a);      // 转发为左值引用
wrapper(10);     // 转发为右值引用
66. 返回值优化(RVO)?

答案:
RVO(Return Value Optimization):

  • 编译器优化:避免不必要的拷贝
  • NRVO:命名返回值优化
  • 条件:返回局部对象
// RVO - 编译器可能优化掉拷贝
String createString() {
    String result("Hello");
    return result;  // 可能直接构造在调用者空间
}

// 更明确的写法
String createString() {
    return String("Hello");  // 更容易被优化
}

// 使用
String s = createString();  // 可能没有拷贝操作
67. 编译期优化的技巧?

答案:
编译期优化技巧:

  • constexpr:编译期计算
  • const:常量传播
  • inline:内联函数
  • 模板元编程:编译期计算
// constexpr - 编译期计算
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;  // 编译期计算
68. 缓存友好的编程?

答案:
缓存友好原则:

  • 局部性原理:时间和空间局部性
  • 数据结构:连续内存访问
  • 循环优化:提高缓存命中率
// 缓存不友好 - 跳跃访问
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]++;  // 行优先访问
        }
    }
}
69. 预分配和容量管理?

答案:
预分配避免重复分配:

  • reserve:预分配容量
  • resize:改变大小并初始化
  • shrink_to_fit:释放多余容量
vector<int> vec;

// 预分配容量
vec.reserve(1000);  // 预分配1000个元素的空间

// 批量插入
for (int i = 0; i < 1000; ++i) {
    vec.push_back(i);  // 不会重新分配
}

// 调整大小
vec.resize(2000);  // 扩展到2000,新元素初始化为0

// 释放多余容量
vec.shrink_to_fit();  // 释放未使用的容量
70. 性能分析工具?

答案:
常用性能分析工具:

  • gprof:GNU性能分析器
  • perf:Linux性能工具
  • Valgrind:内存和性能分析
  • Intel VTune:专业性能分析
# 编译时添加调试信息
g++ -g -pg program.cpp -o program

# 运行程序生成gmon.out
./program

# 分析性能数据
gprof program gmon.out > analysis.txt

# 使用perf分析
perf record ./program
perf report

🏗️ 第四部分:高级特性 (71-85题)

🧵 多线程编程 (71-77)

71. C++11线程的创建和管理?

答案:
C++11线程支持:

  • std::thread:线程类
  • join():等待线程结束
  • detach():分离线程
  • 硬件并发:thread::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();
    
    // 或者分离线程
    // t1.detach();
    
    // 获取硬件并发数
    unsigned int cores = std::thread::hardware_concurrency();
    std::cout << "CPU cores: " << cores << std::endl;
    
    return 0;
}
72. 互斥锁的使用?

答案:
互斥锁保护共享资源:

  • 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;
}
73. 条件变量的使用?

答案:
条件变量实现线程同步:

  • 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();  // 通知所有等待的线程
    }
};
74. 原子操作的使用?

答案:
原子操作无锁编程:

  • 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()};
        
        // CAS操作
        while (!head.compare_exchange_weak(newNode->next, newNode)) {
            // 重试
        }
    }
};
75. 线程安全的单例模式?

答案:
线程安全单例实现:

  • Meyers单例:C++11保证线程安全
  • 双重检查锁定:传统方法
  • std::call_once:C++11保证
// Meyers单例 - C++11线程安全
class Singleton {
public:
    static Singleton& getInstance() {
        static Singleton instance;  // C++11保证线程安全
        return instance;
    }
    
    void doSomething() {
        std::cout << "Doing something" << std::endl;
    }
    
private:
    Singleton() = default;
    ~Singleton() = default;
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
};

// 使用std::call_once
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的使用?

答案:
future/promise异步编程:

  • std::future:获取异步结果
  • std::promise:设置异步结果
  • std::async:异步执行函数
  • std::packaged_task:包装可调用对象
#include <future>
#include <iostream>
#include <chrono>

// 使用std::async
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;
}

// 使用promise
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();
}

// 使用packaged_task
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;
}
77. 线程池的实现?

答案:
线程池管理线程资源:

  • 固定数量线程:避免频繁创建销毁
  • 任务队列:缓存待执行任务
  • 工作线程:从队列取任务执行
#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++特性 (78-85)

78. auto关键字的使用?

答案:
auto自动类型推导:

  • 简化代码:减少冗长类型名
  • 迭代器:简化容器遍历
  • 函数返回值:C++14支持
  • 注意事项:可能降低可读性
#include <vector>
#include <map>
#include <string>

void autoExample() {
    // 基本使用
    auto i = 42;           // int
    auto d = 3.14;         // double
    auto s = "hello";      // const char*
    
    // 容器迭代器
    std::vector<int> vec = {1, 2, 3, 4, 5};
    for (auto it = vec.begin(); it != vec.end(); ++it) {
        std::cout << *it << " ";
    }
    
    // 范围for循环
    for (auto& item : vec) {
        item *= 2;  // 修改元素
    }
    
    // 复杂类型
    std::map<std::string, std::vector<int>> complex_map;
    auto& map_ref = complex_map;  // 引用
    
    // C++14函数返回值推导
    auto add = [](auto a, auto b) {
        return a + b;
    };
    
    auto result = add(3, 4);  // int
    auto result2 = add(3.14, 2.71);  // double
}
79. Lambda表达式的使用?

答案:
Lambda匿名函数:

  • 语法捕获 -> 返回类型 { 函数体 }
  • 捕获方式:值捕获、引用捕获、混合捕获
  • 应用场景:STL算法、回调函数
#include <algorithm>
#include <vector>
#include <iostream>

void lambdaExample() {
    std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    // 基本lambda
    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;
    
    // 可变lambda
    int accumulator = 0;
    auto mutableLambda = [accumulator](int x) mutable {
        accumulator += x;
        return accumulator;
    };
    
    std::cout << mutableLambda(10) << std::endl;  // 10
    std::cout << mutableLambda(20) << std::endl;  // 30
    
    // 泛型lambda (C++14)
    auto genericLambda = [](auto a, auto b) {
        return a + b;
    };
    
    std::cout << genericLambda(3, 4) << std::endl;      // 7
    std::cout << genericLambda(3.14, 2.71) << std::endl; // 5.85
}
80. constexpr的使用?

答案:
constexpr编译期常量:

  • 编译期计算:提高运行时性能
  • 函数和变量:都可以标记为constexpr
  • 限制:只能使用编译期可用的操作
// constexpr变量
constexpr int MAX_SIZE = 100;
constexpr double PI = 3.14159265359;

// constexpr函数
constexpr int factorial(int n) {
    return n <= 1 ? 1 : n * factorial(n - 1);
}

constexpr int fact5 = factorial(5);  // 编译期计算

// constexpr类
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();  // 编译期计算

// constexpr构造函数和成员函数
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;  // 编译期计算
81. 范围for循环的使用?

答案:
范围for循环简化遍历:

  • 语法: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;
    
    // vector遍历
    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 += "!";
    }
    
    // map遍历
    std::map<int, std::string> number_map = {
        {1, "one"}, {2, "two"}, {3, "three"}
    };
    
    for (const auto& [key, value] : number_map) {  // C++17结构化绑定
        std::cout << key << ": " << value << std::endl;
    }
    
    // 自定义类型 - 需要提供begin/end
    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;
}
82. 结构化绑定的使用?

答案:
结构化绑定(C++17)解包复合类型:

  • 语法:auto [a, b] = pair;
  • 适用类型:pair、tuple、数组、结构体
  • 应用场景:简化多返回值处理
#include <tuple>
#include <map>
#include <array>
#include <string>
#include <iostream>

void structuredBindingExample() {
    // pair解包
    std::pair<int, std::string> p = {42, "answer"};
    auto [id, name] = p;
    std::cout << "id: " << id << ", name: " << name << std::endl;
    
    // tuple解包
    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;
    
    // map遍历
    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;
    }
}
83. std::optional的使用?

答案:
std::optional表示可能不存在的值:

  • 替代空指针:类型安全的可选值
  • 避免特殊值:如-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;
    }
    
    // 使用value_or提供默认值
    int value = result2.value_or(0);  // 如果没有值,使用0
    std::cout << "Value: " << value << std::endl;
    
    // 查找用户
    auto user = findUser(2);
    std::cout << "User: " << user.value_or("Unknown") << std::endl;
    
    // optional作为成员变量
    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);  // 默认30秒
        }
    };
    
    Config config;
    config.setTimeout(60);
    std::cout << "Database: " << config.getDatabaseUrl() << std::endl;
    std::cout << "Timeout: " << config.getTimeout() << std::endl;
}
84. std::variant的使用?

答案:
std::variant类型安全的联合体:

  • 类型安全:编译期类型检查
  • 访问方式:std::get、std::visit
  • 应用场景:多类型选择、解析结果
#include <variant>
#include <string>
#include <iostream>
#include <vector>

// variant可以存储多种类型中的一种
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;
    }
    
    // 使用get_if安全访问
    if (auto* str_ptr = std::get_if<std::string>(&v3)) {
        std::cout << "String value: " << *str_ptr << std::endl;
    }
    
    // 使用visitor处理不同类型
    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);
    
    // variant作为函数返回值
    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);
    
    // variant容器
    std::vector<Value> values = {1, 2.5, "three", 4, 5.5};
    
    for (const auto& val : values) {
        std::visit(visitor, val);
    }
}

// 使用variant实现表达式求值
class Expression {
public:
    using Value = std::variant<int, double>;
    
    enum class Op { Add, Subtract, Multiply, Divide };
    
    Expression(Value val) : value_(val), op_(std::nullopt) {}
    Expression(Op op, Expression left, Expression right) 
        : op_(op), left_(std::make_unique<Expression>(left)), 
          right_(std::make_unique<Expression>(right)) {}
    
    Value evaluate() const {
        if (op_) {
            auto left_val = left_->evaluate();
            auto right_val = right_->evaluate();
            
            return std::visit([this](auto&& l, auto&& r) -> Value {
                using L = std::decay_t<decltype(l)>;
                using R = std::decay_t<decltype(r)>;
                
                if constexpr (std::is_same_v<L, int> && std::is_same_v<R, int>) {
                    switch (*op_) {
                        case Op::Add: return l + r;
                        case Op::Subtract: return l - r;
                        case Op::Multiply: return l * r;
                        case Op::Divide: return r != 0 ? l / r : 0;
                    }
                } else {
                    // 转换为double进行计算
                    double dl = static_cast<double>(l);
                    double dr = static_cast<double>(r);
                    switch (*op_) {
                        case Op::Add: return dl + dr;
                        case Op::Subtract: return dl - dr;
                        case Op::Multiply: return dl * dr;
                        case Op::Divide: return dr != 0.0 ? dl / dr : 0.0;
                    }
                }
                return 0;
            }, left_val, right_val);
        }
        return value_;
    }
    
private:
    Value value_;
    std::optional<Op> op_;
    std::unique_ptr<Expression> left_, right_;
};
85. std::any的使用?

答案:
std::any类型安全的任意类型容器:

  • 类型擦除:可以存储任何类型
  • 类型安全:访问时需要类型检查
  • 运行时信息:保存类型信息
#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;
    }
    
    // 使用any_cast安全访问
    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;
    }
    
    // any容器
    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;
        }
    }
    
    // any作为函数参数
    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"));
    
    // any的实用场景:配置系统
    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;
}

🎨 第五部分:设计模式与架构 (86-100题)

🏛️ 设计模式 (86-95)

86. 单例模式的实现?

答案:
单例模式确保类只有一个实例:

  • 饿汉式:程序启动时创建
  • 懒汉式:首次使用时创建
  • 线程安全: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;

// 懒汉式单例(Meyers单例)- C++11线程安全
class LazySingleton {
private:
    LazySingleton() = default;
    ~LazySingleton() = default;
    LazySingleton(const LazySingleton&) = delete;
    LazySingleton& operator=(const LazySingleton&) = delete;
    
public:
    static LazySingleton& getInstance() {
        static LazySingleton instance;  // C++11保证线程安全
        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();
}
87. 工厂模式的实现?

答案:
工厂模式创建对象而不暴露创建逻辑:

  • 简单工厂:一个工厂类创建多种产品
  • 工厂方法:每个产品有对应工厂
  • 抽象工厂:创建产品族
#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();
}
88. 观察者模式的实现?

答案:
观察者模式定义对象间一对多依赖:

  • 主题(Subject):维护观察者列表
  • 观察者(Observer):接收主题通知
  • 松耦合:主题和观察者解耦
#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!");
}
89. 策略模式的实现?

答案:
策略模式定义算法族,可互换使用:

  • 策略接口:定义算法接口
  • 具体策略:实现具体算法
  • 上下文:使用策略对象
#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);
}
90. 装饰器模式的实现?

答案:
装饰器模式动态添加对象功能:

  • 组件接口:定义基础接口
  • 具体组件:实现基础功能
  • 装饰器:添加额外功能
#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;
}
91. 适配器模式的实现?

答案:
适配器模式使不兼容接口协同工作:

  • 目标接口:客户端期望的接口
  • 适配者:需要适配的现有接口
  • 适配器:转换接口
#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 {
        // 内置支持mp3
        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");
}
92. 命令模式的实现?

答案:
命令模式将请求封装为对象:

  • 命令接口:声明执行接口
  • 具体命令:实现命令
  • 调用者:调用命令执行
  • 接收者:执行实际操作
#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;
    
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();
        }
    }
    
private:
    std::unique_ptr<Command> currentCommand;
};

// 使用示例
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();
}
93. 模板方法模式的实现?

答案:
模板方法模式定义算法骨架,子类实现具体步骤:

  • 抽象类:定义模板方法和抽象步骤
  • 具体类:实现具体步骤
#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 XML data" << std::endl;
    }
    
    void saveData() override {
        std::cout << "Saving XML data" << std::endl;
    }
    
    // 使用默认的validateData和cleanup
};

// 使用示例
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();
}
94. 状态模式的实现?

答案:
状态模式允许对象在内部状态改变时改变行为:

  • 状态接口:定义状态行为
  • 具体状态:实现状态行为
  • 上下文:维护当前状态
#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;
}
95. 代理模式的实现?

答案:
代理模式为其他对象提供代理以控制访问:

  • 主题接口:定义真实主题和代理的公共接口
  • 真实主题:实现实际业务逻辑
  • 代理:控制对真实主题的访问
#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;
}

🏗️ 架构设计 (96-100)

96. SOLID原则的解释?

答案:
SOLID是面向对象设计的五个基本原则:

S - 单一职责原则 (SRP)

  • 一个类应该只有一个引起变化的原因
  • 每个类只负责一个功能
// 违反SRP
class User {
public:
    void saveToDatabase() { /* 数据库操作 */ }
    void validateEmail() { /* 验证逻辑 */ }
    void sendEmail() { /* 邮件发送 */ }
};

// 遵循SRP
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)

  • 对扩展开放,对修改关闭
  • 通过继承和组合实现扩展
// 违反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;
    }
};

// 遵循OCP
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)

  • 子类必须能够替换其基类
  • 子类不应破坏基类的约定
// 违反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"); 
    }
};

// 遵循LSP
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)

  • 客户端不应依赖它不需要的接口
  • 将大接口拆分为小接口
// 违反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 { /* 机器人不需要睡觉 */ }
};

// 遵循ISP
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)

  • 高层模块不应依赖低层模块,都应依赖抽象
  • 抽象不应依赖细节,细节应依赖抽象
// 违反DIP
class LightBulb {
public:
    void turnOn() { std::cout << "LightBulb on" << std::endl; }
};

class Switch {
private:
    LightBulb bulb;
public:
    Switch() : bulb() {}
    void press() { bulb.turnOn(); }
};

// 遵循DIP
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(); }
};
97. 依赖注入的实现?

答案:
依赖注入(DI)将依赖关系外部注入:

  • 构造函数注入:通过构造函数注入依赖
  • Setter注入:通过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) {}
    
    // Setter注入
    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");
    }
};

// 简单的DI容器
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");
    
    // 使用DI容器
    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");
    }
}
98. 代码组织和模块化?

答案:
良好的代码组织和模块化:

  • 分层架构:表示层、业务层、数据层
  • 模块划分:按功能职责划分
  • 接口设计:清晰的模块边界
// 数据访问层
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("john@example.com", "password123");
    userController->registerUser("invalid-email", "short");
}
99. 测试驱动开发(TDD)?

答案:
TDD开发流程:

  1. 编写测试:先写失败的测试
  2. 运行测试:确认测试失败
  3. 编写代码:最小化代码使测试通过
  4. 重构:优化代码保持测试通过
// 测试框架简化版
#define ASSERT_TRUE(condition) \
    if (!(condition)) { \
        std::cout << "FAIL: " << #condition << " at line " << __LINE__ << std::endl; \
    } else { \
        std::cout << "PASS: " << #condition << std::endl; \
    }

#define ASSERT_EQ(expected, actual) \
    if ((expected) != (actual)) { \
        std::cout << "FAIL: expected " << (expected) << " but got " << (actual) << " at line " << __LINE__ << std::endl; \
    } else { \
        std::cout << "PASS: " << (expected) << " == " << (actual) << std::endl; \
    }

// TDD示例:计算器类
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); // 期望的异常
    }
}

// TDD流程示例
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());
    
    // 测试push
    stack.push(1);
    ASSERT_FALSE(stack.isEmpty());
    ASSERT_EQ(1, stack.size());
    
    stack.push(2);
    ASSERT_EQ(2, stack.size());
    
    // 测试pop
    ASSERT_EQ(2, stack.pop());
    ASSERT_EQ(1, stack.size());
    
    ASSERT_EQ(1, stack.pop());
    ASSERT_TRUE(stack.isEmpty());
    
    // 测试空栈pop异常
    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();
}
100. C++最佳实践总结?

答案:
C++开发最佳实践:

代码风格

  • 使用一致的命名约定
  • 保持函数和类的职责单一
  • 添加适当的注释和文档
  • 遵循项目编码规范

内存管理

  • 优先使用智能指针
  • 遵循RAII原则
  • 避免内存泄漏和野指针
  • 合理使用移动语义

性能优化

  • 选择合适的容器和算法
  • 避免不必要的拷贝
  • 使用编译期优化
  • 进行性能分析

错误处理

  • 使用异常处理错误情况
  • 提供清晰的错误信息
  • 保证异常安全
  • 合理使用noexcept

现代C++特性

  • 使用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;
    
    // 使用const和noexcept
    size_t size() const noexcept { return size_; }
    
    // 使用范围for循环友好的接口
    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和auto
    constexpr static size_t max_size() noexcept {
        return 1000000;
    }
};

// 使用示例
void bestPracticeExample() {
    try {
        ModernCppExample example(10);
        
        // 使用auto和范围for循环
        for (auto& item : example) {
            item = 42;
        }
        
        // 使用STL算法
        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原则、依赖注入、模块化

💡 面试准备建议

  1. 理解原理:不要死记硬背,理解底层机制
  2. 动手实践:多写代码,积累实际经验
  3. 关注现代C++:掌握C++11/14/17/20新特性
  4. 项目经验:结合实际项目理解概念
  5. 持续学习:C++标准不断更新,保持学习

祝你面试成功!🎉

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值