C++核心特性精讲:从C语言痛点出发,掌握现代C++编程精髓(超详细)

C++核心特性精讲:从C语言痛点出发,掌握现代C++编程精髓

引言:为什么需要从C转向C++?

C语言作为结构化编程的典范,自1972年诞生以来,在系统编程、嵌入式开发等领域占据着不可替代的地位。然而,随着软件规模的不断扩大,C语言在大型项目管理、代码安全性、开发效率等方面逐渐暴露出诸多不足:

  • 名字冲突问题:缺乏有效的模块隔离机制
  • 指针使用复杂:手动管理内存,容易产生内存泄漏和悬空指针
  • 函数设计死板:参数传递缺乏灵活性
  • 宏定义缺陷:类型不安全,调试困难
  • 缺乏数据封装:面向过程的设计难以应对复杂业务逻辑

C++作为C的超集,不仅100%兼容C语言,更引入了面向对象、泛型编程和现代C++特性,为开发者提供了一整套系统性的解决方案。本文将深入剖析C语言的核心痛点,并通过丰富的代码示例展示C++如何优雅地解决这些问题。

一、解决名字冲突:命名空间(namespace)

1.1 C语言的命名冲突痛点

在C语言中,所有的全局标识符(变量、函数)都共享同一个全局命名空间。当项目规模增大时,这种设计会导致严重的问题:

c 复制代码
// module1.c
int add(int a, int b) {
    return a + b;
}

// module2.c
int add(int a, int b, int c) {
    return a + b + c;
}

// main.c
int main() {
    // 编译错误:重复定义的符号
    int result = add(1, 2);
    return 0;
}

此外,与标准库的冲突也时常发生:

c 复制代码
#include <stdlib.h>

// 与标准库函数重名
void* malloc(size_t size) {
    // 自定义内存分配器
    return custom_alloc(size);
}

int main() {
    // 调用哪个malloc?存在歧义
    void* p = malloc(100);
    return 0;
}

1.2 C++的解决方案:命名空间

C++引入了命名空间的概念,为标识符提供了逻辑上的分组机制,有效避免了名字冲突。

1.2.1 基本命名空间
cpp 复制代码
#include <iostream>

// 定义数学计算命名空间
namespace Math {
    const double PI = 3.141592653589793;
    
    int add(int a, int b) {
        return a + b;
    }
    
    double add(double a, double b) {
        return a + b;
    }
    
    class Calculator {
    public:
        int multiply(int a, int b) {
            return a * b;
        }
    };
}

// 定义图形计算命名空间
namespace Graphics {
    // 与Math::add不冲突
    void add(int x, int y) {
        std::cout << "移动图形到(" << x << ", " << y << ")" << std::endl;
    }
    
    class Point {
    private:
        int x_, y_;
    public:
        Point(int x, int y) : x_(x), y_(y) {}
        void draw() const {
            std::cout << "绘制点(" << x_ << ", " << y_ << ")" << std::endl;
        }
    };
}

int main() {
    // 方式1:完全限定名
    std::cout << "Math::PI = " << Math::PI << std::endl;
    std::cout << "Math::add(5, 3) = " << Math::add(5, 3) << std::endl;
    
    // 方式2:using声明(引入特定标识符)
    using Math::Calculator;
    Calculator calc;
    std::cout << "5 * 3 = " << calc.multiply(5, 3) << std::endl;
    
    // 方式3:using指令(引入整个命名空间)
    using namespace Graphics;
    add(10, 20);  // 调用Graphics::add
    
    // 不同命名空间的同名函数不冲突
    Math::add(1.5, 2.5);  // 调用Math::add(double, double)
    
    return 0;
}
1.2.2 嵌套命名空间

C++支持命名空间的嵌套,提供了更精细的模块划分:

cpp 复制代码
#include <iostream>
#include <string>

namespace Company {
    namespace Project {
        namespace Module {
            
            class Database {
            private:
                std::string connection_string_;
                
            public:
                Database(const std::string& conn_str) 
                    : connection_string_(conn_str) {}
                
                void connect() {
                    std::cout << "连接到数据库: " 
                              << connection_string_ << std::endl;
                }
            };
            
            // C++17引入的简化嵌套语法
            namespace Utils {
                std::string format(const std::string& str) {
                    return "[" + str + "]";
                }
            }
        }
    }
}

// C++17语法:简化嵌套命名空间
namespace Company::Project::Network {
    class Socket {
    public:
        void send(const std::string& data) {
            std::cout << "发送数据: " << data << std::endl;
        }
    };
}

int main() {
    // 访问嵌套命名空间
    Company::Project::Module::Database db("localhost:3306");
    db.connect();
    
    // 使用简化语法(C++17)
    Company::Project::Network::Socket socket;
    socket.send("Hello");
    
    return 0;
}
1.2.3 匿名命名空间

匿名命名空间用于定义仅在当前编译单元中可见的标识符:

cpp 复制代码
// file1.cpp
namespace {
    // 仅在file1.cpp中可见
    int internal_counter = 0;
    
    void internal_function() {
        // 内部实现细节
    }
}

// file2.cpp
namespace {
    // 与file1.cpp中的internal_counter不冲突
    int internal_counter = 100;
}

// 等效于C语言中的static函数/变量,但更安全
1.2.4 命名空间别名

对于过长的命名空间名称,可以创建简短的别名:

cpp 复制代码
#include <iostream>

namespace VeryLongNamespaceName {
    void importantFunction() {
        std::cout << "重要功能" << std::endl;
    }
}

// 创建别名
namespace VLN = VeryLongNamespaceName;
namespace S = std;  // 不推荐,仅作示例

int main() {
    VLN::importantFunction();  // 使用别名
    
    // 函数内部的局部别名
    namespace Math = VeryLongNamespaceName;
    Math::importantFunction();
    
    return 0;
}

1.3 实际工程中的应用

1.3.1 大型项目中的命名空间管理
cpp 复制代码
// 项目结构示例:
// - core/          (核心功能)
//   - math.hpp     (数学库)
//   - utils.hpp    (工具函数)
// - network/       (网络模块)
// - database/      (数据库模块)

// core/math.hpp
#pragma once

namespace MyProject::Core::Math {
    
    class Vector3D {
    private:
        double x_, y_, z_;
        
    public:
        Vector3D(double x, double y, double z) 
            : x_(x), y_(y), z_(z) {}
        
        // 向量运算
        Vector3D operator+(const Vector3D& other) const;
        Vector3D operator-(const Vector3D& other) const;
        double dot(const Vector3D& other) const;
        
        // 静态工厂方法
        static Vector3D zero() { return Vector3D(0, 0, 0); }
        static Vector3D one() { return Vector3D(1, 1, 1); }
    };
    
    // 数学常量
    namespace Constants {
        const double E = 2.718281828459045;
        const double SQRT2 = 1.414213562373095;
    }
    
    // 线性代数函数
    namespace LinearAlgebra {
        template<typename T, int N>
        class Matrix {
            // 矩阵实现
        };
    }
}

// network/socket.hpp
#pragma once

namespace MyProject::Network {
    
    class Socket {
    public:
        enum class Protocol {
            TCP,
            UDP,
            SSL
        };
        
        explicit Socket(Protocol protocol);
        virtual ~Socket();
        
        virtual bool connect(const std::string& host, int port) = 0;
        virtual void disconnect() = 0;
        virtual size_t send(const void* data, size_t size) = 0;
        virtual size_t receive(void* buffer, size_t size) = 0;
    };
    
    // 工厂函数
    std::unique_ptr<Socket> createSocket(Socket::Protocol protocol);
}

// main.cpp
#include "core/math.hpp"
#include "network/socket.hpp"

int main() {
    using namespace MyProject;
    
    // 使用数学模块
    Core::Math::Vector3D v1(1.0, 2.0, 3.0);
    Core::Math::Vector3D v2(4.0, 5.0, 6.0);
    
    auto sum = v1 + v2;
    
    // 使用网络模块
    auto socket = Network::createSocket(Network::Socket::Protocol::TCP);
    
    return 0;
}
1.3.2 命名空间的最佳实践
cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>

// 最佳实践示例
namespace BestPractices {
    
    // 1. 避免在头文件中使用using namespace
    // 错误做法:
    // using namespace std;  // 污染全局命名空间
    
    // 正确做法:
    // 在头文件中使用完全限定名或局部using声明
    
    // 2. 使用内联命名空间进行版本控制
    namespace v1 {
        class API {
        public:
            void doSomething() {
                std::cout << "v1 API" << std::endl;
            }
        };
    }
    
    inline namespace v2 {  // v2成为默认版本
        class API {
        public:
            void doSomething() {
                std::cout << "v2 API (默认)" << std::endl;
            }
            
            void newFeature() {
                std::cout << "v2新功能" << std::endl;
            }
        };
    }
    
    // 3. 使用ADL(参数依赖查找)
    namespace ADLDemo {
        class MyString {
            std::string data_;
        public:
            MyString(const char* str) : data_(str) {}
            
            // 友元函数可以在命名空间外定义
            friend std::ostream& operator<<(std::ostream& os, 
                                          const MyString& str);
        };
        
        // ADL会找到这个函数
        std::ostream& operator<<(std::ostream& os, const MyString& str) {
            return os << "MyString: " << str.data_;
        }
    }
}

int main() {
    // 版本控制示例
    BestPractices::API api_default;  // 使用v2(默认)
    api_default.doSomething();
    api_default.newFeature();
    
    // 明确指定版本
    BestPractices::v1::API api_v1;
    api_v1.doSomething();
    
    // ADL示例
    BestPractices::ADLDemo::MyString str("Hello");
    std::cout << str << std::endl;  // ADL自动找到正确的operator<<
    
    return 0;
}

二、函数传参更灵活:缺省参数

2.1 C语言函数传参的限制

C语言中,函数调用必须提供所有参数,即使某些参数在大多数情况下使用相同的值:

c 复制代码
#include <stdio.h>

// 打印日志函数
void log_message(const char* message, int level, 
                 const char* file, int line) {
    printf("[%d] %s:%d: %s\n", level, file, line, message);
}

int main() {
    // 每次调用都要重复相同的参数
    log_message("程序启动", 1, __FILE__, __LINE__);
    log_message("用户登录", 2, __FILE__, __LINE__);
    log_message("数据库错误", 3, __FILE__, __LINE__);
    
    // 无法简化常用参数的传递
    return 0;
}

2.2 C++缺省参数详解

2.2.1 基本用法
cpp 复制代码
#include <iostream>
#include <string>

// 1. 全缺省参数
void print(const std::string& message, 
           int level = 1,  // 默认级别为1
           bool timestamp = true,  // 默认包含时间戳
           const std::string& prefix = "LOG") {  // 默认前缀
    
    if (timestamp) {
        // 模拟时间戳
        std::cout << "[2024-01-01 12:00:00] ";
    }
    
    std::cout << "[" << prefix << "] ";
    std::cout << "Level " << level << ": ";
    std::cout << message << std::endl;
}

// 2. 半缺省参数(从右向左连续)
void connect(const std::string& hostname,
             int port = 80,  // 默认HTTP端口
             int timeout = 30,  // 默认超时30秒
             bool use_ssl = false) {  // 默认不使用SSL
    
    std::cout << "连接到 " << hostname << ":" << port;
    std::cout << " (超时: " << timeout << "秒)";
    std::cout << " SSL: " << (use_ssl ? "是" : "否") << std::endl;
}

// 3. 带有复杂类型的缺省参数
class LoggerConfig {
public:
    std::string format = "[{level}] {message}";
    bool color_output = false;
    int max_file_size = 1024 * 1024;  // 1MB
};

void configure_logger(const LoggerConfig& config = LoggerConfig()) {
    std::cout << "日志配置:" << std::endl;
    std::cout << "  格式: " << config.format << std::endl;
    std::cout << "  彩色输出: " << (config.color_output ? "是" : "否") << std::endl;
    std::cout << "  最大文件大小: " << config.max_file_size << " bytes" << std::endl;
}

int main() {
    // 使用不同参数组合调用
    print("程序启动");  // 使用所有默认值
    print("警告信息", 2);  // 只指定级别
    print("错误信息", 3, false);  // 指定级别和时间戳
    print("致命错误", 4, true, "ERROR");  // 指定所有参数
    
    std::cout << std::endl;
    
    // 网络连接示例
    connect("example.com");  // 仅指定主机名
    connect("api.example.com", 443);  // 指定主机名和端口
    connect("secure.example.com", 8443, 60, true);  // 指定所有参数
    
    std::cout << std::endl;
    
    // 使用默认配置对象
    configure_logger();
    
    // 自定义配置
    LoggerConfig custom_config;
    custom_config.format = "{timestamp} [{level}] {file}:{line} {message}";
    custom_config.color_output = true;
    configure_logger(custom_config);
    
    return 0;
}
2.2.2 缺省参数的声明与定义

在大型项目中,函数的声明通常放在头文件中,定义放在源文件中。缺省参数只能出现在函数声明中:

cpp 复制代码
// logger.h - 头文件
#pragma once
#include <string>

namespace Logger {
    
    // 声明函数,指定缺省参数
    void debug(const std::string& message, 
               const std::string& file = __FILE__, 
               int line = __LINE__);
    
    void error(const std::string& message,
               const std::string& file = __FILE__,
               int line = __LINE__,
               bool send_email = false);
}

// logger.cpp - 源文件
#include "logger.h"
#include <iostream>
#include <ctime>

namespace Logger {
    
    // 定义函数时不重复缺省参数
    void debug(const std::string& message, 
               const std::string& file, 
               int line) {
        auto now = std::time(nullptr);
        std::cout << "[DEBUG] " << std::ctime(&now);
        std::cout << "  " << file << ":" << line << std::endl;
        std::cout << "  " << message << std::endl;
    }
    
    void error(const std::string& message,
               const std::string& file,
               int line,
               bool send_email) {
        auto now = std::time(nullptr);
        std::cout << "[ERROR] " << std::ctime(&now);
        std::cout << "  " << file << ":" << line << std::endl;
        std::cout << "  " << message << std::endl;
        
        if (send_email) {
            std::cout << "  错误报告已发送到管理员邮箱" << std::endl;
        }
    }
}

// main.cpp - 使用示例
#include "logger.h"

int main() {
    Logger::debug("应用程序启动");
    Logger::error("数据库连接失败");
    Logger::error("内存分配失败", __FILE__, __LINE__, true);
    
    return 0;
}
2.2.3 缺省参数与函数重载的配合

缺省参数可以与函数重载结合使用,提供更灵活的接口:

cpp 复制代码
#include <iostream>
#include <string>
#include <vector>

class DataProcessor {
public:
    // 重载版本1:处理单个数据
    void process(int data, 
                 const std::string& algorithm = "default") {
        std::cout << "处理单个整数: " << data;
        std::cout << " (算法: " << algorithm << ")" << std::endl;
    }
    
    // 重载版本2:处理数组
    void process(const std::vector<int>& data,
                 const std::string& algorithm = "default",
                 bool normalize = true) {
        std::cout << "处理整数数组 (大小: " << data.size() << ")";
        std::cout << " (算法: " << algorithm << ")";
        std::cout << " (归一化: " << (normalize ? "是" : "否") << ")" << std::endl;
    }
    
    // 重载版本3:处理字符串
    void process(const std::string& data,
                 bool case_sensitive = false,
                 const std::string& encoding = "UTF-8") {
        std::cout << "处理字符串: " << data;
        std::cout << " (大小写敏感: " << (case_sensitive ? "是" : "否") << ")";
        std::cout << " (编码: " << encoding << ")" << std::endl;
    }
};

int main() {
    DataProcessor processor;
    
    // 使用不同重载和缺省参数
    processor.process(42);  // 调用版本1
    processor.process(100, "advanced");  // 调用版本1
    
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    processor.process(numbers);  // 调用版本2
    processor.process(numbers, "fast", false);  // 调用版本2
    
    processor.process("Hello World");  // 调用版本3
    processor.process("C++ Programming", true, "ASCII");  // 调用版本3
    
    return 0;
}
2.2.4 缺省参数的陷阱与注意事项
cpp 复制代码
#include <iostream>

// 陷阱1:缺省参数在编译时确定
int get_default_value() {
    static int counter = 0;
    return ++counter;
}

void func_with_pitfall(int x = get_default_value()) {
    std::cout << "x = " << x << std::endl;
}

// 陷阱2:虚函数的缺省参数
class Base {
public:
    virtual void display(int level = 1) const {
        std::cout << "Base::display(level=" << level << ")" << std::endl;
    }
};

class Derived : public Base {
public:
    void display(int level = 2) const override {  // 注意:缺省参数不同!
        std::cout << "Derived::display(level=" << level << ")" << std::endl;
    }
};

// 解决方案:使用函数重载避免缺省参数问题
class SafeBase {
public:
    virtual void display() const {
        display(1);  // 调用带参数的版本
    }
    
    virtual void display(int level) const {
        std::cout << "SafeBase::display(level=" << level << ")" << std::endl;
    }
    
    virtual ~SafeBase() = default;
};

class SafeDerived : public SafeBase {
public:
    void display() const override {
        display(2);  // 调用带参数的版本
    }
    
    void display(int level) const override {
        std::cout << "SafeDerived::display(level=" << level << ")" << std::endl;
    }
};

int main() {
    // 陷阱1示例:缺省参数只计算一次
    std::cout << "陷阱1示例:" << std::endl;
    func_with_pitfall();  // x = 1
    func_with_pitfall();  // x = 1(不是2!)
    func_with_pitfall(10);  // x = 10
    
    std::cout << "\n陷阱2示例:" << std::endl;
    // 陷阱2示例:虚函数的缺省参数
    Derived derived;
    Base* base_ptr = &derived;
    
    derived.display();  // 输出:Derived::display(level=2)
    base_ptr->display();  // 输出:Derived::display(level=1) ⚠️
    
    std::cout << "\n解决方案示例:" << std::endl;
    // 使用重载的解决方案
    SafeDerived safe_derived;
    SafeBase* safe_base_ptr = &safe_derived;
    
    safe_derived.display();  // 输出:SafeDerived::display(level=2)
    safe_base_ptr->display();  // 输出:SafeDerived::display(level=2) ✓
    
    return 0;
}

2.3 现代C++中的改进:统一初始化与委托构造函数

cpp 复制代码
#include <iostream>
#include <string>
#include <vector>

class ModernExample {
private:
    std::string name_;
    int value_;
    std::vector<int> data_;
    
public:
    // 委托构造函数:一个构造函数调用另一个
    ModernExample() : ModernExample("default", 0) {}
    
    ModernExample(const std::string& name) : ModernExample(name, 100) {}
    
    ModernExample(const std::string& name, int value) 
        : name_(name), value_(value) {
        // 使用统一初始化语法
        data_ = {1, 2, 3, 4, 5};
    }
    
    // 统一初始化语法
    ModernExample(std::initializer_list<int> init_list)
        : name_("from_init_list"), value_(static_cast<int>(init_list.size())) {
        data_.assign(init_list.begin(), init_list.end());
    }
    
    void print() const {
        std::cout << "Name: " << name_ << ", Value: " << value_;
        std::cout << ", Data: [";
        for (size_t i = 0; i < data_.size(); ++i) {
            if (i > 0) std::cout << ", ";
            std::cout << data_[i];
        }
        std::cout << "]" << std::endl;
    }
};

// 使用统一初始化的函数
void process_data(std::vector<int> data = {1, 2, 3, 4, 5}) {
    std::cout << "处理数据: [";
    for (size_t i = 0; i < data.size(); ++i) {
        if (i > 0) std::cout << ", ";
        std::cout << data[i];
    }
    std::cout << "]" << std::endl;
}

int main() {
    // 使用不同方式构造对象
    ModernExample obj1;  // 使用默认构造函数
    ModernExample obj2("test");  // 使用单参数构造函数
    ModernExample obj3("custom", 42);  // 使用完整构造函数
    ModernExample obj4{10, 20, 30, 40};  // 使用初始化列表
    
    obj1.print();
    obj2.print();
    obj3.print();
    obj4.print();
    
    // 函数调用中的统一初始化
    process_data();  // 使用默认值
    process_data({5, 10, 15});  // 传递初始化列表
    
    return 0;
}

三、变量的"外号":引用(&)

3.1 C语言指针的痛点

c 复制代码
#include <stdio.h>
#include <stdlib.h>

// C语言中必须使用指针来修改外部变量
void swap_c(int* a, int* b) {
    if (!a || !b) {  // 必须检查空指针
        return;
    }
    int temp = *a;  // 需要解引用
    *a = *b;
    *b = temp;
}

// 复杂的指针操作容易出错
void process_array_c(int** array, int* size) {
    if (!array || !*array || !size) {
        return;
    }
    
    // 复杂的指针解引用
    for (int i = 0; i < *size; i++) {
        (*array)[i] *= 2;  // 容易写错为 *array[i]
    }
}

int main() {
    int x = 10, y = 20;
    swap_c(&x, &y);  // 必须使用取地址操作符
    
    int* arr = malloc(5 * sizeof(int));
    int size = 5;
    
    // 复杂的参数传递
    process_array_c(&arr, &size);
    
    free(arr);
    return 0;
}

3.2 C++引用的基本概念

3.2.1 引用的基本用法
cpp 复制代码
#include <iostream>
#include <string>

// 1. 基本引用类型
void basic_reference_demo() {
    std::cout << "=== 基本引用示例 ===" << std::endl;
    
    int original = 42;
    int& ref = original;  // 引用必须初始化
    
    std::cout << "original = " << original << std::endl;
    std::cout << "ref = " << ref << std::endl;
    
    // 修改引用就是修改原变量
    ref = 100;
    std::cout << "修改ref后:" << std::endl;
    std::cout << "original = " << original << std::endl;
    std::cout << "ref = " << ref << std::endl;
    
    // 引用一旦绑定就不能更改绑定对象
    int another = 200;
    ref = another;  // 这不是重新绑定,而是赋值操作
    std::cout << "ref = another 后:" << std::endl;
    std::cout << "original = " << original << std::endl;  // original被修改为200
    std::cout << "another = " << another << std::endl;    // another仍然是200
}

// 2. 引用作为函数参数(替代指针)
void swap_cpp(int& a, int& b) {
    int temp = a;  // 无需解引用,语法更简洁
    a = b;
    b = temp;
}

// 3. 引用作为函数返回值
class LargeObject {
private:
    int data_[1000];
    
public:
    int& operator[](size_t index) {
        if (index >= 1000) {
            static int dummy = 0;
            return dummy;
        }
        return data_[index];
    }
    
    const int& operator[](size_t index) const {
        if (index >= 1000) {
            static const int dummy = 0;
            return dummy;
        }
        return data_[index];
    }
    
    // 返回成员变量的引用
    int& first() { return data_[0]; }
    const int& first() const { return data_[0]; }
};

// 4. 链式调用(返回引用实现)
class Calculator {
private:
    double value_;
    
public:
    Calculator(double initial = 0) : value_(initial) {}
    
    Calculator& add(double x) {
        value_ += x;
        return *this;
    }
    
    Calculator& subtract(double x) {
        value_ -= x;
        return *this;
    }
    
    Calculator& multiply(double x) {
        value_ *= x;
        return *this;
    }
    
    Calculator& divide(double x) {
        if (x != 0) {
            value_ /= x;
        }
        return *this;
    }
    
    double get() const { return value_; }
};

int main() {
    basic_reference_demo();
    
    std::cout << "\n=== 引用作为函数参数 ===" << std::endl;
    int x = 10, y = 20;
    std::cout << "交换前: x=" << x << ", y=" << y << std::endl;
    swap_cpp(x, y);  // 无需取地址,语法更直观
    std::cout << "交换后: x=" << x << ", y=" << y << std::endl;
    
    std::cout << "\n=== 引用作为函数返回值 ===" << std::endl;
    LargeObject obj;
    
    // 使用引用返回值可以直接修改对象内部
    obj[0] = 42;  // operator[]返回引用
    obj[1] = 100;
    
    std::cout << "obj[0] = " << obj[0] << std::endl;
    std::cout << "obj[1] = " << obj[1] << std::endl;
    
    // 链式调用示例
    std::cout << "\n=== 链式调用 ===" << std::endl;
    Calculator calc(10);
    calc.add(5).multiply(2).subtract(3).divide(4);
    std::cout << "计算结果: " << calc.get() << std::endl;
    
    return 0;
}
3.2.2 引用与指针的对比
cpp 复制代码
#include <iostream>
#include <vector>

void compare_reference_pointer() {
    std::cout << "=== 引用与指针对比 ===" << std::endl;
    
    int value = 42;
    
    // 指针:存储地址的变量
    int* ptr = &value;
    
    // 引用:变量的别名
    int& ref = value;
    
    std::cout << "原始值: " << value << std::endl;
    std::cout << "指针值: " << *ptr << std::endl;
    std::cout << "引用值: " << ref << std::endl;
    
    // 修改对比
    *ptr = 100;  // 通过指针修改
    std::cout << "通过指针修改后: " << value << std::endl;
    
    ref = 200;   // 通过引用修改
    std::cout << "通过引用修改后: " << value << std::endl;
    
    // 重新指向对比
    int another = 300;
    ptr = &another;  // 指针可以重新指向
    // ref = another; // 这不是重新绑定,而是赋值
    
    // 空值对比
    ptr = nullptr;  // 指针可以为空
    // int& bad_ref; // 错误:引用必须初始化
    // int& null_ref = nullptr; // 错误:不能绑定到nullptr
}

// 在实际项目中的应用选择
class DataProcessor {
public:
    // 情况1:需要修改参数 - 使用引用
    void process_data(std::vector<int>& data) {
        for (auto& item : data) {
            item *= 2;  // 直接修改原数据
        }
    }
    
    // 情况2:不需要修改但避免拷贝 - 使用const引用
    double calculate_average(const std::vector<int>& data) const {
        if (data.empty()) return 0.0;
        
        double sum = 0;
        for (const auto& item : data) {
            sum += item;
        }
        return sum / data.size();
    }
    
    // 情况3:参数可选 - 使用指针(或std::optional)
    bool find_value(const std::vector<int>& data, int target, int* position = nullptr) {
        for (size_t i = 0; i < data.size(); ++i) {
            if (data[i] == target) {
                if (position) {  // 检查指针是否有效
                    *position = static_cast<int>(i);
                }
                return true;
            }
        }
        return false;
    }
    
    // 情况4:返回动态分配的对象 - 使用智能指针
    std::unique_ptr<std::vector<int>> create_filtered_data(
        const std::vector<int>& data,
        std::function<bool(int)> predicate) {
        
        auto result = std::make_unique<std::vector<int>>();
        for (const auto& item : data) {
            if (predicate(item)) {
                result->push_back(item);
            }
        }
        return result;
    }
};

int main() {
    compare_reference_pointer();
    
    std::cout << "\n=== 在实际项目中的应用 ===" << std::endl;
    DataProcessor processor;
    
    std::vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    // 情况1:需要修改数据
    std::cout << "原始数据: ";
    for (const auto& item : data) std::cout << item << " ";
    std::cout << std::endl;
    
    processor.process_data(data);
    
    std::cout << "处理后的数据: ";
    for (const auto& item : data) std::cout << item << " ";
    std::cout << std::endl;
    
    // 情况2:只读访问
    double avg = processor.calculate_average(data);
    std::cout << "平均值: " << avg << std::endl;
    
    // 情况3:可选参数
    int position = -1;
    if (processor.find_value(data, 10, &position)) {
        std::cout << "找到10,位置: " << position << std::endl;
    }
    
    // 情况4:返回动态对象
    auto filtered = processor.create_filtered_data(
        data, [](int x) { return x % 2 == 0; });
    
    std::cout << "偶数数据: ";
    for (const auto& item : *filtered) std::cout << item << " ";
    std::cout << std::endl;
    
    return 0;
}
3.2.3 引用的高级用法
cpp 复制代码
#include <iostream>
#include <array>
#include <functional>
#include <memory>

// 1. 引用包装器(std::reference_wrapper)
void reference_wrapper_demo() {
    std::cout << "=== 引用包装器 ===" << std::endl;
    
    int x = 10, y = 20, z = 30;
    
    // 创建引用包装器
    std::reference_wrapper<int> ref_x = x;
    std::reference_wrapper<int> ref_y = y;
    
    // 可以存储在容器中
    std::vector<std::reference_wrapper<int>> numbers = {ref_x, ref_y};
    
    // 可以通过get()获取原始引用
    numbers.push_back(z);  // 隐式转换
    
    // 修改
    for (auto& ref : numbers) {
        ref.get() *= 2;
    }
    
    std::cout << "x = " << x << std::endl;  // 20
    std::cout << "y = " << y << std::endl;  // 40
    std::cout << "z = " << z << std::endl;  // 60
    
    // 使用std::ref和std::cref
    auto print_value = [](int& val) { std::cout << val << " "; };
    
    std::for_each(numbers.begin(), numbers.end(), 
                  [&](std::reference_wrapper<int> ref) {
                      print_value(ref);
                  });
    std::cout << std::endl;
}

// 2. 完美转发中的引用(现代C++重要特性)
template<typename T>
void process_impl(T&& value) {
    // 使用std::forward实现完美转发
    std::cout << "处理值: " << std::forward<T>(value) << std::endl;
}

template<typename... Args>
void process_all(Args&&... args) {
    // 折叠表达式(C++17)
    (process_impl(std::forward<Args>(args)), ...);
}

// 3. 引用与移动语义
class Resource {
private:
    std::unique_ptr<int[]> data_;
    size_t size_;
    
public:
    Resource(size_t size) : size_(size) {
        data_ = std::make_unique<int[]>(size);
        std::cout << "分配 " << size << " 个整数" << std::endl;
    }
    
    // 移动构造函数
    Resource(Resource&& other) noexcept
        : data_(std::move(other.data_)), size_(other.size_) {
        other.size_ = 0;
        std::cout << "移动构造" << std::endl;
    }
    
    // 移动赋值运算符
    Resource& operator=(Resource&& other) noexcept {
        if (this != &other) {
            data_ = std::move(other.data_);
            size_ = other.size_;
            other.size_ = 0;
            std::cout << "移动赋值" << std::endl;
        }
        return *this;
    }
    
    // 删除拷贝操作
    Resource(const Resource&) = delete;
    Resource& operator=(const Resource&) = delete;
    
    ~Resource() {
        if (data_) {
            std::cout << "释放资源" << std::endl;
        }
    }
    
    int& operator[](size_t index) {
        return data_[index];
    }
    
    size_t size() const { return size_; }
};

// 4. 右值引用(C++11引入)
void rvalue_reference_demo() {
    std::cout << "\n=== 右值引用 ===" << std::endl;
    
    int x = 42;
    
    // 左值引用(绑定到左值)
    int& lref = x;
    
    // 右值引用(绑定到临时对象)
    int&& rref = 100;  // 100是右值
    
    // 右值引用可以延长临时对象的生命周期
    const std::string& s1 = std::string("临时字符串");
    
    // 移动语义示例
    Resource res1(100);
    Resource res2 = std::move(res1);  // 使用移动构造函数
    
    std::cout << "res1.size() = " << res1.size() << std::endl;  // 0
    std::cout << "res2.size() = " << res2.size() << std::endl;  // 100
}

int main() {
    reference_wrapper_demo();
    
    std::cout << "\n=== 完美转发 ===" << std::endl;
    int x = 42;
    const int y = 100;
    
    // 完美转发保持值类别
    process_all(x, y, 200, std::string("Hello"));
    
    rvalue_reference_demo();
    
    return 0;
}

四、更安全的引用:const引用

4.1 const引用的基本概念

cpp 复制代码
#include <iostream>
#include <string>
#include <vector>

// 1. const引用的基本用法
void const_reference_basics() {
    std::cout << "=== const引用基础 ===" << std::endl;
    
    int x = 10;
    const int y = 20;
    
    // 普通引用
    int& ref_x = x;          // OK
    // int& ref_y = y;       // 错误:不能将普通引用绑定到const变量
    
    // const引用
    const int& cref_x = x;   // OK:const引用可以绑定到非const变量
    const int& cref_y = y;   // OK:const引用可以绑定到const变量
    
    // 通过const引用访问
    std::cout << "cref_x = " << cref_x << std::endl;
    std::cout << "cref_y = " << cref_y << std::endl;
    
    // 不能通过const引用修改原值
    // cref_x = 100;         // 错误:cref_x是const引用
    x = 100;                // OK:可以直接修改原变量
    std::cout << "修改x后,cref_x = " << cref_x << std::endl;
}

// 2. const引用绑定临时对象
void temporary_object_demo() {
    std::cout << "\n=== const引用绑定临时对象 ===" << std::endl;
    
    // const引用可以延长临时对象的生命周期
    const std::string& str_ref = std::string("临时字符串");
    std::cout << "临时字符串: " << str_ref << std::endl;
    
    // 不同类型转换
    double d = 3.14159;
    const int& int_ref = d;  // 创建临时int对象并绑定
    std::cout << "double转int: " << d << " -> " << int_ref << std::endl;
    
    // 表达式结果
    int a = 10, b = 20;
    const int& sum_ref = a + b;  // 绑定到表达式结果的临时对象
    std::cout << "a + b = " << sum_ref << std::endl;
}

// 3. const引用作为函数参数
class DataAnalyzer {
public:
    // const引用避免拷贝,同时保证不修改数据
    double calculate_mean(const std::vector<double>& data) const {
        if (data.empty()) return 0.0;
        
        double sum = 0.0;
        for (const double& value : data) {  // 循环中使用const引用
            sum += value;
        }
        return sum / data.size();
    }
    
    // 查找数据中的最大值
    const double& find_max(const std::vector<double>& data) const {
        if (data.empty()) {
            static const double empty_value = 0.0;
            return empty_value;
        }
        
        const double* max_ptr = &data[0];
        for (const double& value : data) {
            if (value > *max_ptr) {
                max_ptr = &value;
            }
        }
        return *max_ptr;  // 返回const引用,避免拷贝
    }
    
    // 同时需要可读和可写的版本
    double& get_reference(std::vector<double>& data, size_t index) {
        return data[index];  // 返回非const引用,允许修改
    }
    
    const double& get_reference(const std::vector<double>& data, size_t index) const {
        return data[index];  // 返回const引用,只读访问
    }
};

// 4. const成员函数
class BankAccount {
private:
    std::string owner_;
    mutable double balance_;  // mutable允许在const函数中修改
    
public:
    BankAccount(const std::string& owner, double initial_balance)
        : owner_(owner), balance_(initial_balance) {}
    
    // const成员函数:不修改对象状态
    const std::string& get_owner() const {
        return owner_;
    }
    
    double get_balance() const {
        return balance_;
    }
    
    // 非const成员函数:允许修改对象状态
    void deposit(double amount) {
        if (amount > 0) {
            balance_ += amount;
        }
    }
    
    // const函数中修改mutable成员
    void audit_trail() const {
        // 可以修改mutable成员
        static int audit_count = 0;
        audit_count++;
        std::cout << "第" << audit_count << "次审计" << std::endl;
    }
    
    // 重载:const和非const版本
    std::string& details() {
        std::cout << "非const版本" << std::endl;
        return owner_;
    }
    
    const std::string& details() const {
        std::cout << "const版本" << std::endl;
        return owner_;
    }
};

int main() {
    const_reference_basics();
    temporary_object_demo();
    
    std::cout << "\n=== const引用在数据分析中的应用 ===" << std::endl;
    DataAnalyzer analyzer;
    
    std::vector<double> data = {1.5, 2.5, 3.5, 4.5, 5.5};
    
    double mean = analyzer.calculate_mean(data);
    std::cout << "平均值: " << mean << std::endl;
    
    const double& max_value = analyzer.find_max(data);
    std::cout << "最大值: " << max_value << std::endl;
    
    // 使用const版本
    const std::vector<double>& const_data = data;
    const double& const_ref = analyzer.get_reference(const_data, 0);
    std::cout << "const引用: " << const_ref << std::endl;
    
    // 使用非const版本
    double& nonconst_ref = analyzer.get_reference(data, 0);
    nonconst_ref = 10.0;
    std::cout << "修改后: " << data[0] << std::endl;
    
    std::cout << "\n=== const成员函数 ===" << std::endl;
    BankAccount account("张三", 1000.0);
    const BankAccount& const_account = account;
    
    // const对象只能调用const成员函数
    std::cout << "账户所有者: " << const_account.get_owner() << std::endl;
    std::cout << "账户余额: " << const_account.get_balance() << std::endl;
    
    // 调用const版本的details
    const std::string& const_details = const_account.details();
    
    // 非const对象可以调用所有函数
    account.deposit(500.0);
    std::cout << "存款后余额: " << account.get_balance() << std::endl;
    
    // 调用非const版本的details
    std::string& nonconst_details = account.details();
    nonconst_details = "李四";
    std::cout << "修改后所有者: " << account.get_owner() << std::endl;
    
    // mutable成员
    account.audit_trail();
    const_account.audit_trail();
    
    return 0;
}

4.2 const正确性的重要性

cpp 复制代码
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

// 1. const正确性避免错误
class Configuration {
private:
    std::vector<std::string> settings_;
    mutable std::size_t access_count_ = 0;  // 访问计数器
    
public:
    void add_setting(const std::string& setting) {
        settings_.push_back(setting);
    }
    
    // 错误的设计:返回非const引用
    std::string& get_setting_bad(size_t index) {
        return settings_[index];  // 外部可以修改内部数据
    }
    
    // 正确的设计:根据constness返回不同引用
    const std::string& get_setting_good(size_t index) const {
        access_count_++;  // mutable,可以在const函数中修改
        return settings_[index];
    }
    
    std::string& get_setting_good(size_t index) {
        return settings_[index];
    }
    
    size_t get_access_count() const {
        return access_count_;
    }
};

// 2. const在STL算法中的应用
void stl_const_demo() {
    std::cout << "\n=== const在STL算法中的应用 ===" << std::endl;
    
    std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    const std::vector<int>& const_numbers = numbers;
    
    // const容器的迭代器也是const的
    auto const_begin = const_numbers.begin();
    auto const_end = const_numbers.end();
    
    // 使用const迭代器遍历
    std::cout << "const遍历: ";
    for (auto it = const_begin; it != const_end; ++it) {
        std::cout << *it << " ";
        // *it = 0;  // 错误:不能通过const迭代器修改值
    }
    std::cout << std::endl;
    
    // 非const容器的非const迭代器
    std::cout << "修改前: ";
    for (const auto& num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;
    
    // 使用算法修改数据
    std::for_each(numbers.begin(), numbers.end(), 
                  [](int& n) { n *= 2; });
    
    std::cout << "修改后: ";
    for (const auto& num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;
}

// 3. constexpr(C++11引入的编译期常量)
class MathConstants {
public:
    // constexpr函数可以在编译期计算
    static constexpr double PI = 3.141592653589793;
    
    constexpr static double square(double x) {
        return x * x;
    }
    
    // constexpr构造函数
    constexpr MathConstants(double value) : value_(value) {}
    
    constexpr double get_value() const { return value_; }
    
private:
    double value_;
};

// 4. const指针 vs const引用
void const_pointer_vs_reference() {
    std::cout << "\n=== const指针 vs const引用 ===" << std::endl;
    
    int value = 42;
    const int const_value = 100;
    
    // const指针
    const int* ptr1 = &value;       // 指向const int的指针
    int const* ptr2 = &value;       // 同上,语法不同
    int* const ptr3 = &value;       // const指针,指向int
    const int* const ptr4 = &value; // const指针,指向const int
    
    // const引用
    const int& ref1 = value;        // const引用
    const int& ref2 = const_value;  // const引用
    
    // 修改测试
    value = 50;  // OK
    
    // 通过指针修改
    // *ptr1 = 60;    // 错误:ptr1指向const int
    // *ptr2 = 60;    // 错误:ptr2指向const int
    *ptr3 = 70;       // OK:ptr3是指向int的const指针
    // *ptr4 = 80;    // 错误:ptr4指向const int
    
    // 修改指针本身
    int another = 200;
    ptr1 = &another;  // OK:ptr1本身不是const
    // ptr3 = &another; // 错误:ptr3是const指针
    
    // 引用不能重新绑定
    // ref1 = another; // 错误:不能给引用重新赋值
    
    std::cout << "value = " << value << std::endl;
    std::cout << "*ptr3 = " << *ptr3 << std::endl;
    std::cout << "ref1 = " << ref1 << std::endl;
}

// 5. 实际工程中的const使用
class DatabaseConnection {
private:
    mutable std::string last_query_;  // 缓存最后一次查询
    mutable std::size_t query_count_ = 0;
    
public:
    // const函数中的复杂操作
    std::vector<std::string> execute_query(const std::string& query) const {
        // 记录查询历史(修改mutable成员)
        last_query_ = query;
        query_count_++;
        
        // 模拟数据库查询
        std::cout << "执行查询: " << query << std::endl;
        
        // 返回查询结果
        return {"结果1", "结果2", "结果3"};
    }
    
    // 获取最后查询(const版本)
    const std::string& get_last_query() const {
        return last_query_;
    }
    
    // 获取查询计数(const版本)
    std::size_t get_query_count() const {
        return query_count_;
    }
};

int main() {
    // 1. Configuration示例
    Configuration config;
    config.add_setting("timeout=30");
    config.add_setting("retry=3");
    
    // 危险:可以直接修改内部数据
    config.get_setting_bad(0) = "hacked!";
    
    const Configuration& const_config = config;
    
    // 安全:只能读取,不能修改
    std::cout << "设置: " << const_config.get_setting_good(0) << std::endl;
    std::cout << "访问次数: " << const_config.get_access_count() << std::endl;
    
    stl_const_demo();
    
    std::cout << "\n=== constexpr示例 ===" << std::endl;
    // 编译期计算
    constexpr double pi_squared = MathConstants::square(MathConstants::PI);
    constexpr MathConstants constants(3.14);
    
    std::cout << "PI = " << MathConstants::PI << std::endl;
    std::cout << "PI^2 = " << pi_squared << std::endl;
    std::cout << "常量值 = " << constants.get_value() << std::endl;
    
    const_pointer_vs_reference();
    
    std::cout << "\n=== 数据库连接示例 ===" << std::endl;
    DatabaseConnection db;
    const DatabaseConnection& const_db = db;
    
    auto results = const_db.execute_query("SELECT * FROM users");
    std::cout << "查询结果数量: " << results.size() << std::endl;
    std::cout << "最后查询: " << const_db.get_last_query() << std::endl;
    std::cout << "查询次数: " << const_db.get_query_count() << std::endl;
    
    return 0;
}

五、指针和引用的核心区别

5.1 详细对比分析

cpp 复制代码
#include <iostream>
#include <memory>
#include <functional>

class DetailedComparison {
public:
    static void syntax_and_usage() {
        std::cout << "=== 语法和使用方式对比 ===" << std::endl;
        
        int value = 42;
        
        // 指针语法
        int* ptr = &value;      // 需要取地址
        *ptr = 100;             // 需要解引用
        ptr = nullptr;          // 可以置空
        
        // 引用语法
        int& ref = value;       // 直接绑定,无需取地址
        ref = 200;              // 直接使用,无需解引用
        // ref = nullptr;       // 错误:不能绑定到nullptr
        
        std::cout << "value = " << value << std::endl;
        std::cout << "*ptr = " << *ptr << std::endl;
        std::cout << "ref = " << ref << std::endl;
    }
    
    static void memory_and_lifetime() {
        std::cout << "\n=== 内存和生命周期对比 ===" << std::endl;
        
        // 指针有自己的内存空间
        int x = 10;
        int* ptr = &x;
        
        std::cout << "x的地址: " << &x << std::endl;
        std::cout << "ptr的值: " << ptr << std::endl;
        std::cout << "ptr的地址: " << &ptr << std::endl;
        std::cout << "ptr的大小: " << sizeof(ptr) << " bytes" << std::endl;
        
        // 引用不占用额外内存(编译器实现细节)
        int& ref = x;
        std::cout << "ref的大小: " << sizeof(ref) << " bytes" << std::endl;
        
        // 动态内存管理
        int* dynamic_ptr = new int(100);
        // int& dynamic_ref = *new int(200); // 危险:内存泄漏
        
        delete dynamic_ptr;
        // delete &dynamic_ref; // 语法奇怪,容易出错
    }
    
    static void safety_comparison() {
        std::cout << "\n=== 安全性对比 ===" << std::endl;
        
        // 空指针问题
        int* ptr = nullptr;
        if (ptr) {  // 必须检查
            *ptr = 42;
        }
        
        // 引用不能为空(更安全)
        int value = 10;
        int& ref = value;  // 总是有效
        // int& bad_ref;    // 错误:必须初始化
        
        // 野指针问题
        int* wild_ptr;  // 未初始化,危险!
        // int& wild_ref; // 错误:必须初始化
        
        // 悬空指针/引用
        int* dangling_ptr = new int(100);
        int& dangling_ref = *dangling_ptr;
        
        delete dangling_ptr;  // 释放内存
        
        // 现在dangling_ptr和dangling_ref都无效
        // *dangling_ptr = 200;  // 未定义行为
        // dangling_ref = 300;    // 未定义行为
    }
    
    static void polymorphism_and_inheritance() {
        std::cout << "\n=== 多态性和继承对比 ===" << std::endl;
        
        class Base {
        public:
            virtual void show() { std::cout << "Base" << std::endl; }
            virtual ~Base() = default;
        };
        
        class Derived : public Base {
        public:
            void show() override { std::cout << "Derived" << std::endl; }
        };
        
        Derived derived;
        
        // 指针:天然支持多态
        Base* ptr = &derived;
        ptr->show();  // 输出:Derived
        
        // 引用:也支持多态
        Base& ref = derived;
        ref.show();   // 输出:Derived
        
        // 但引用不能重新绑定到其他对象
        Base base;
        // ref = base;  // 这是赋值,不是重新绑定
    }
    
    static void performance_considerations() {
        std::cout << "\n=== 性能考虑 ===" << std::endl;
        
        // 引用通常没有性能开销
        // 编译器通常将引用实现为指针,但优化后可能直接使用原始变量
        
        const int size = 1000000;
        std::vector<int> data(size, 42);
        
        // 通过引用传递大对象避免拷贝
        auto process_by_ref = [](std::vector<int>& vec) {
            for (auto& item : vec) {
                item *= 2;
            }
        };
        
        // 通过指针传递
        auto process_by_ptr = [](std::vector<int>* vec) {
            if (vec) {
                for (auto& item : *vec) {
                    item /= 2;
                }
            }
        };
        
        // 性能基本相同,但引用语法更简洁
        process_by_ref(data);
        process_by_ptr(&data);
        
        std::cout << "处理完成" << std::endl;
    }
    
    static void modern_cpp_features() {
        std::cout << "\n=== 现代C++特性 ===" << std::endl;
        
        // 1. 智能指针(替代原始指针)
        auto smart_ptr = std::make_unique<int>(42);
        std::shared_ptr<int> shared = std::make_shared<int>(100);
        
        // 2. 引用包装器
        int x = 10, y = 20;
        std::vector<std::reference_wrapper<int>> refs = {x, y};
        
        // 3. 完美转发需要引用折叠
        auto forward_example = []<typename T>(T&& arg) {
            // 通用引用(引用折叠)
            return std::forward<T>(arg);
        };
        
        // 4. 结构化绑定(C++17)
        std::pair<int, std::string> pair{42, "answer"};
        auto& [num, str] = pair;  // 引用绑定
        
        std::cout << "num = " << num << ", str = " << str << std::endl;
    }
};

// 实际工程中的选择指南
class EngineeringGuidelines {
public:
    // 规则1:优先使用引用作为函数参数
    void process_data(std::vector<int>& data) {  // 需要修改参数
        // ...
    }
    
    void analyze_data(const std::vector<int>& data) {  // 不需要修改
        // ...
    }
    
    // 规则2:使用指针表示可选参数
    bool find_value(const std::vector<int>& data, 
                   int target, 
                   int* found_index = nullptr) {
        for (size_t i = 0; i < data.size(); ++i) {
            if (data[i] == target) {
                if (found_index) {
                    *found_index = static_cast<int>(i);
                }
                return true;
            }
        }
        return false;
    }
    
    // 规则3:使用智能指针管理动态内存
    std::unique_ptr<int[]> create_buffer(size_t size) {
        return std::make_unique<int[]>(size);
    }
    
    // 规则4:返回引用时需要小心生命周期
    const std::string& get_name() const {
        static const std::string default_name = "default";
        return default_name;  // 返回静态变量的引用是安全的
    }
    
    // 危险:返回局部变量的引用
    const std::string& bad_get_name() const {
        std::string local_name = "local";
        return local_name;  // 错误:返回局部变量的引用
    }
    
    // 规则5:在类设计中使用引用成员需要小心
    class Observer {
    private:
        std::function<void()>& callback_;  // 引用成员
    public:
        explicit Observer(std::function<void()>& callback)
            : callback_(callback) {}  // 必须在初始化列表中初始化
        
        void notify() {
            callback_();
        }
    };
};

int main() {
    DetailedComparison::syntax_and_usage();
    DetailedComparison::memory_and_lifetime();
    DetailedComparison::safety_comparison();
    DetailedComparison::polymorphism_and_inheritance();
    DetailedComparison::performance_considerations();
    DetailedComparison::modern_cpp_features();
    
    std::cout << "\n=== 工程实践示例 ===" << std::endl;
    EngineeringGuidelines guidelines;
    
    std::vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    // 使用引用参数
    guidelines.process_data(data);
    
    // 使用可选指针参数
    int found_index = -1;
    if (guidelines.find_value(data, 5, &found_index)) {
        std::cout << "找到5,索引: " << found_index << std::endl;
    }
    
    // 使用智能指针
    auto buffer = guidelines.create_buffer(100);
    std::cout << "创建缓冲区大小: 100" << std::endl;
    
    // 安全返回引用
    const std::string& name = guidelines.get_name();
    std::cout << "名称: " << name << std::endl;
    
    return 0;
}

5.2 选择指针还是引用:决策树

cpp 复制代码
#include <iostream>
#include <memory>
#include <optional>
#include <functional>

// 决策辅助类
class ReferenceOrPointer {
public:
    // 场景1:函数参数传递
    static void function_parameters() {
        std::cout << "=== 函数参数传递决策 ===" << std::endl;
        
        // 情况A:需要修改参数且参数不为空 -> 使用引用
        void modify_in_place(std::string& str);  // 推荐
        
        // 情况B:需要修改参数且参数可能为空 -> 使用指针
        bool try_modify(std::string* str);  // 推荐
        
        // 情况C:不需要修改但避免拷贝 -> 使用const引用
        void read_only(const std::string& str);  // 推荐
        
        // 情况D:原始数组 -> 使用指针
        void process_array(int* array, size_t size);  // 推荐
        
        // 现代C++:考虑使用视图
        void process_span(std::span<int> data);  // C++20推荐
    }
    
    // 场景2:返回值
    static void return_values() {
        std::cout << "\n=== 返回值决策 ===" << std::endl;
        
        // 情况A:返回内部状态的引用 -> 小心生命周期
        class Container {
            std::vector<int> data_;
        public:
            // 返回引用允许修改
            int& operator[](size_t index) { return data_[index]; }
            
            // 返回const引用只读访问
            const int& operator[](size_t index) const { return data_[index]; }
            
            // 危险:返回局部变量引用
            const std::string& bad_method() const {
                std::string local = "bad";
                return local;  // 错误!
            }
            
            // 安全:返回成员引用
            const std::vector<int>& get_data() const { return data_; }
        };
        
        // 情况B:返回动态分配的对象 -> 使用智能指针
        std::unique_ptr<int[]> create_array(size_t size) {
            return std::make_unique<int[]>(size);
        }
        
        // 情况C:可能没有值 -> 使用std::optional
        std::optional<int> find_value(const std::vector<int>& data, int target) {
            for (int value : data) {
                if (value == target) {
                    return value;
                }
            }
            return std::nullopt;
        }
    }
    
    // 场景3:类成员
    static void class_members() {
        std::cout << "\n=== 类成员决策 ===" << std::endl;
        
        // 情况A:拥有关系 -> 使用值或智能指针
        class Owner {
            std::unique_ptr<int> resource_;  // 拥有资源
            std::vector<int> data_;          // 拥有数据
        };
        
        // 情况B:观察关系 -> 使用原始指针或weak_ptr
        class Observer {
            // Subject* subject_;  // 不拥有,观察
            // std::weak_ptr<Subject> subject_;  // 更好的选择
        };
        
        // 情况C:关联关系 -> 使用引用(必须初始化)
        class Processor {
            std::function<void()>& callback_;  // 关联回调
        public:
            explicit Processor(std::function<void()>& callback)
                : callback_(callback) {}
        };
        
        // 情况D:可选关联 -> 使用指针
        class Configurable {
            const Config* config_ = nullptr;  // 可选配置
        public:
            void set_config(const Config* config) {
                config_ = config;
            }
        };
    }
    
    // 场景4:多态性
    static void polymorphism() {
        std::cout << "\n=== 多态性决策 ===" << std::endl;
        
        class Shape {
        public:
            virtual void draw() const = 0;
            virtual ~Shape() = default;
        };
        
        class Circle : public Shape {
        public:
            void draw() const override {
                std::cout << "绘制圆形" << std::endl;
            }
        };
        
        class Square : public Shape {
        public:
            void draw() const override {
                std::cout << "绘制方形" << std::endl;
            }
        };
        
        // 情况A:存储多态对象 -> 使用指针或智能指针
        std::vector<std::unique_ptr<Shape>> shapes;
        shapes.push_back(std::make_unique<Circle>());
        shapes.push_back(std::make_unique<Square>());
        
        // 情况B:传递多态参数 -> 使用引用
        void render_shape(const Shape& shape) {
            shape.draw();  // 多态调用
        }
        
        // 情况C:返回多态对象 -> 使用智能指针
        std::unique_ptr<Shape> create_shape(const std::string& type) {
            if (type == "circle") return std::make_unique<Circle>();
            if (type == "square") return std::make_unique<Square>();
            return nullptr;
        }
    }
    
    // 场景5:性能关键代码
    static void performance_critical() {
        std::cout << "\n=== 性能关键代码决策 ===" << std::endl;
        
        // 情况A:小对象传值,大对象传引用
        struct Small { int x, y; };  // 传值
        struct Large { int data[1000]; };  // 传引用
        
        void process_small(Small s) {}  // 推荐:传值
        void process_large(const Large& l) {}  // 推荐:传引用
        
        // 情况B:内联函数 -> 通常传值
        inline int add(int a, int b) { return a + b; }
        
        // 情况C:热点循环 -> 使用引用避免拷贝
        void process_vector(std::vector<int>& vec) {
            for (int& item : vec) {  // 使用引用避免拷贝
                item *= 2;
            }
        }
        
        // 情况D:底层操作 -> 使用指针
        void memcpy_impl(void* dest, const void* src, size_t n) {
            // 底层内存操作通常使用指针
        }
    }
};

// 综合示例
class Database {
private:
    struct Connection {
        int id;
        std::string name;
    };
    
    std::vector<std::unique_ptr<Connection>> connections_;
    mutable std::size_t query_count_ = 0;
    
public:
    // 返回智能指针(拥有关系)
    std::unique_ptr<Connection> create_connection(const std::string& name) {
        auto conn = std::make_unique<Connection>();
        conn->id = static_cast<int>(connections_.size());
        conn->name = name;
        connections_.push_back(std::move(conn));
        return std::make_unique<Connection>(*connections_.back());
    }
    
    // 返回引用(内部对象,调用者不拥有)
    Connection& get_connection(int id) {
        if (id >= 0 && id < static_cast<int>(connections_.size())) {
            return *connections_[id];
        }
        throw std::out_of_range("无效的连接ID");
    }
    
    // 返回const引用(只读访问)
    const Connection& get_connection(int id) const {
        if (id >= 0 && id < static_cast<int>(connections_.size())) {
            query_count_++;  // 修改mutable成员
            return *connections_[id];
        }
        throw std::out_of_range("无效的连接ID");
    }
    
    // 使用指针表示可选返回值
    Connection* find_connection(const std::string& name) {
        for (auto& conn : connections_) {
            if (conn->name == name) {
                return conn.get();
            }
        }
        return nullptr;  // 使用nullptr表示没找到
    }
    
    // 使用引用传递回调
    void for_each_connection(std::function<void(const Connection&)> callback) const {
        for (const auto& conn : connections_) {
            callback(*conn);
        }
    }
};

int main() {
    ReferenceOrPointer::function_parameters();
    ReferenceOrPointer::return_values();
    ReferenceOrPointer::class_members();
    ReferenceOrPointer::polymorphism();
    ReferenceOrPointer::performance_critical();
    
    std::cout << "\n=== 数据库综合示例 ===" << std::endl;
    Database db;
    
    // 创建连接(返回智能指针)
    auto conn1 = db.create_connection("主数据库");
    auto conn2 = db.create_connection("备份数据库");
    
    // 获取引用(内部对象)
    Database::Connection& ref = db.get_connection(0);
    ref.name = "修改后的主数据库";
    
    // 使用指针查找
    Database::Connection* ptr = db.find_connection("备份数据库");
    if (ptr) {
        std::cout << "找到连接: " << ptr->name << std::endl;
    }
    
    // 使用引用传递回调
    db.for_each_connection([](const Database::Connection& conn) {
        std::cout << "连接ID: " << conn.id 
                  << ", 名称: " << conn.name << std::endl;
    });
    
    return 0;
}

六、替代宏函数:inline内联函数

6.1 C语言宏函数的缺陷

cpp 复制代码
#include <iostream>
#include <cstdlib>

// C语言宏函数的典型问题
void macro_problems_demo() {
    std::cout << "=== C语言宏函数的缺陷 ===" << std::endl;
    
    // 问题1:缺乏类型检查
    #define MAX(a, b) ((a) > (b) ? (a) : (b))
    
    int x = 5, y = 10;
    std::cout << "MAX(5, 10) = " << MAX(x, y) << std::endl;
    
    double d1 = 3.14, d2 = 2.71;
    std::cout << "MAX(3.14, 2.71) = " << MAX(d1, d2) << std::endl;
    
    // 危险:不同类型混合
    std::cout << "MAX(5, 2.71) = " << MAX(x, d2) << std::endl;  // 编译通过,但有警告
    
    // 问题2:运算符优先级问题
    #define SQUARE(x) x * x
    
    int a = 5;
    std::cout << "SQUARE(5) = " << SQUARE(a) << std::endl;  // 25,正确
    std::cout << "SQUARE(5+1) = " << SQUARE(a + 1) << std::endl;  // 11,错误!
    // 展开为:5 + 1 * 5 + 1 = 5 + 5 + 1 = 11
    
    // 问题3:多次求值
    #define PRINT_AND_INCREMENT(x) \
        std::cout << "值: " << (x) << std::endl; \
        (x)++
    
    int counter = 0;
    std::cout << "\n多次求值问题:" << std::endl;
    std::cout << "MAX(counter++, 10) = " << MAX(counter++, 10) << std::endl;
    std::cout << "counter = " << counter << std::endl;  // counter被增加了2次!
    
    // 问题4:无法调试
    // 宏在预处理阶段展开,调试器中看不到宏函数
    
    // 问题5:作用域问题
    #define TEMP_VAR 100
    int TEMP_VAR = 200;  // 编译错误:重定义
    
    std::cout << "\n";
}

// 复杂的宏带来的问题
void complex_macro_issues() {
    std::cout << "=== 复杂宏的问题 ===" << std::endl;
    
    // 复杂的宏难以阅读和维护
    #define CREATE_PERSON(name, age) \
        Person p##name = {#name, age}; \
        register_person(&p##name)
    
    struct Person {
        const char* name;
        int age;
    };
    
    void register_person(Person* p) {
        std::cout << "注册: " << p->name << ", " << p->age << "岁" << std::endl;
    }
    
    // 使用宏
    CREATE_PERSON(Alice, 25);
    CREATE_PERSON(Bob, 30);
    
    // 问题:##运算符的滥用
    #define GET_FIELD(obj, field) (obj).field_##field
    
    struct Data {
        int field_id;
        std::string field_name;
    };
    
    Data data{42, "test"};
    std::cout << "ID: " << GET_FIELD(data, id) << std::endl;
    std::cout << "Name: " << GET_FIELD(data, name) << std::endl;
    
    // 但宏不能处理动态字段名
    std::cout << "\n";
}

6.2 inline内联函数的解决方案

cpp 复制代码
#include <iostream>
#include <string>
#include <type_traits>
#include <cmath>

// 1. 基本inline函数
inline int max_int(int a, int b) {
    return a > b ? a : b;
}

inline double max_double(double a, double b) {
    return a > b ? a : b;
}

// 2. 模板inline函数(类型安全)
template<typename T>
inline T max_template(T a, T b) {
    return a > b ? a : b;
}

// 3. 带约束的模板(C++20)
template<typename T>
requires std::is_arithmetic_v<T>
inline T max_constrained(T a, T b) {
    return a > b ? a : b;
}

// 4. 类内定义的成员函数默认inline
class MathUtils {
public:
    // 类内定义的成员函数默认inline
    static int square(int x) {
        return x * x;
    }
    
    static double square(double x) {
        return x * x;
    }
    
    // 模板成员函数
    template<typename T>
    static T cube(T x) {
        return x * x * x;
    }
};

// 5. 复杂的inline函数示例
class Vector3D {
private:
    double x_, y_, z_;
    
public:
    Vector3D(double x = 0, double y = 0, double z = 0)
        : x_(x), y_(y), z_(z) {}
    
    // 内联getter/setter
    inline double x() const { return x_; }
    inline double y() const { return y_; }
    inline double z() const { return z_; }
    
    inline void set_x(double x) { x_ = x; }
    inline void set_y(double y) { y_ = y; }
    inline void set_z(double z) { z_ = z; }
    
    // 内联运算符
    inline Vector3D operator+(const Vector3D& other) const {
        return Vector3D(x_ + other.x_, y_ + other.y_, z_ + other.z_);
    }
    
    inline Vector3D operator-(const Vector3D& other) const {
        return Vector3D(x_ - other.x_, y_ - other.y_, z_ - other.z_);
    }
    
    inline double dot(const Vector3D& other) const {
        return x_ * other.x_ + y_ * other.y_ + z_ * other.z_;
    }
    
    inline double length() const {
        return std::sqrt(dot(*this));
    }
    
    inline Vector3D normalized() const {
        double len = length();
        if (len > 0) {
            return Vector3D(x_ / len, y_ / len, z_ / len);
        }
        return *this;
    }
    
    // 静态内联工厂方法
    static inline Vector3D zero() { return Vector3D(0, 0, 0); }
    static inline Vector3D one() { return Vector3D(1, 1, 1); }
    static inline Vector3D up() { return Vector3D(0, 1, 0); }
    static inline Vector3D right() { return Vector3D(1, 0, 0); }
    static inline Vector3D forward() { return Vector3D(0, 0, 1); }
};

void inline_function_demo() {
    std::cout << "=== inline函数解决方案 ===" << std::endl;
    
    // 基本使用
    std::cout << "max_int(5, 10) = " << max_int(5, 10) << std::endl;
    std::cout << "max_double(3.14, 2.71) = " << max_double(3.14, 2.71) << std::endl;
    
    // 模板版本(类型安全)
    std::cout << "max_template(5, 10) = " << max_template(5, 10) << std::endl;
    std::cout << "max_template(3.14, 2.71) = " << max_template(3.14, 2.71) << std::endl;
    
    // 类型检查
    // max_template(5, 2.71);  // 编译错误:类型不匹配
    
    // 带约束的模板
    std::cout << "max_constrained(5, 10) = " << max_constrained(5, 10) << std::endl;
    // max_constrained("a", "b");  // 编译错误:不满足约束
    
    // 类内函数
    std::cout << "MathUtils::square(5) = " << MathUtils::square(5) << std::endl;
    std::cout << "MathUtils::cube(3) = " << MathUtils::cube(3) << std::endl;
    
    // Vector3D示例
    Vector3D v1(1, 2, 3);
    Vector3D v2(4, 5, 6);
    
    Vector3D sum = v1 + v2;
    std::cout << "向量相加: (" << sum.x() << ", " << sum.y() << ", " << sum.z() << ")" << std::endl;
    
    double dot_product = v1.dot(v2);
    std::cout << "点积: " << dot_product << std::endl;
    
    std::cout << "v1长度: " << v1.length() << std::endl;
    
    Vector3D normalized = v1.normalized();
    std::cout << "归一化: (" << normalized.x() << ", " << normalized.y() << ", " << normalized.z() << ")" << std::endl;
    
    // 使用静态工厂方法
    Vector3D zero = Vector3D::zero();
    Vector3D up = Vector3D::up();
    std::cout << "零向量: (" << zero.x() << ", " << zero.y() << ", " << zero.z() << ")" << std::endl;
    std::cout << "上向量: (" << up.x() << ", " << up.y() << ", " << up.z() << ")" << std::endl;
}

// 6. inline函数的性能分析
class PerformanceAnalyzer {
public:
    // 适合inline的小函数
    inline bool is_even(int n) const {
        return (n & 1) == 0;
    }
    
    inline int clamp(int value, int min, int max) const {
        if (value < min) return min;
        if (value > max) return max;
        return value;
    }
    
    inline float lerp(float a, float b, float t) const {
        return a + t * (b - a);
    }
    
    // 不适合inline的大函数
    void complex_calculation(std::vector<int>& data) {
        // 复杂操作,不应该inline
        std::sort(data.begin(), data.end());
        // ... 更多复杂操作
    }
    
    // 递归函数通常不能inline
    int fibonacci(int n) {
        if (n <= 1) return n;
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
};

// 7. inline与constexpr的结合(C++11起)
class CompileTimeMath {
public:
    // constexpr函数默认inline
    constexpr static int factorial(int n) {
        return n <= 1 ? 1 : n * factorial(n - 1);
    }
    
    constexpr static bool is_prime(int n) {
        if (n <= 1) return false;
        for (int i = 2; i * i <= n; ++i) {
            if (n % i == 0) return false;
        }
        return true;
    }
    
    // C++14起允许更复杂的constexpr函数
    constexpr static int sum_squares(int n) {
        int sum = 0;
        for (int i = 1; i <= n; ++i) {
            sum += i * i;
        }
        return sum;
    }
};

void constexpr_inline_demo() {
    std::cout << "\n=== constexpr inline函数 ===" << std::endl;
    
    // 编译期计算
    constexpr int fact_5 = CompileTimeMath::factorial(5);
    constexpr bool prime_17 = CompileTimeMath::is_prime(17);
    constexpr int squares_10 = CompileTimeMath::sum_squares(10);
    
    std::cout << "5! = " << fact_5 << std::endl;
    std::cout << "17是质数? " << (prime_17 ? "是" : "否") << std::endl;
    std::cout << "1²+2²+...+10² = " << squares_10 << std::endl;
    
    // 运行时使用
    for (int i = 0; i <= 10; ++i) {
        std::cout << i << "! = " << CompileTimeMath::factorial(i) << std::endl;
    }
}

// 8. 实际工程中的inline使用
class StringUtils {
public:
    // 适合inline的字符串辅助函数
    inline static bool starts_with(const std::string& str, const std::string& prefix) {
        return str.size() >= prefix.size() && 
               str.compare(0, prefix.size(), prefix) == 0;
    }
    
    inline static bool ends_with(const std::string& str, const std::string& suffix) {
        return str.size() >= suffix.size() && 
               str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
    }
    
    inline static std::string trim_left(const std::string& str) {
        size_t start = str.find_first_not_of(" \t\n\r\f\v");
        return (start == std::string::npos) ? "" : str.substr(start);
    }
    
    inline static std::string trim_right(const std::string& str) {
        size_t end = str.find_last_not_of(" \t\n\r\f\v");
        return (end == std::string::npos) ? "" : str.substr(0, end + 1);
    }
    
    inline static std::string trim(const std::string& str) {
        return trim_right(trim_left(str));
    }
    
    // 不适合inline的复杂字符串处理
    static std::vector<std::string> split(const std::string& str, char delimiter);
};

int main() {
    macro_problems_demo();
    complex_macro_issues();
    inline_function_demo();
    constexpr_inline_demo();
    
    std::cout << "\n=== 字符串工具示例 ===" << std::endl;
    
    std::string text = "   Hello, World!   ";
    std::cout << "原始: \"" << text << "\"" << std::endl;
    std::cout << "修剪后: \"" << StringUtils::trim(text) << "\"" << std::endl;
    
    std::string filename = "document.pdf";
    std::cout << "文件名: " << filename << std::endl;
    std::cout << "是否以.pdf结尾? " 
              << (StringUtils::ends_with(filename, ".pdf") ? "是" : "否") << std::endl;
    
    std::string url = "https://example.com";
    std::cout << "URL: " << url << std::endl;
    std::cout << "是否以https开头? " 
              << (StringUtils::starts_with(url, "https") ? "是" : "否") << std::endl;
    
    return 0;
}

6.3 inline的注意事项和最佳实践

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>

// 1. inline只是建议,编译器可能忽略
class InlineGuidelines {
public:
    // 适合inline的情况:
    
    // a) 简单的getter/setter
    inline int get_value() const { return value_; }
    inline void set_value(int v) { value_ = v; }
    
    // b) 简单的数学运算
    inline static double degrees_to_radians(double degrees) {
        return degrees * 3.141592653589793 / 180.0;
    }
    
    // c) 小的工具函数
    inline static bool is_power_of_two(unsigned int n) {
        return n && !(n & (n - 1));
    }
    
    // 不适合inline的情况:
    
    // a) 函数体太大
    void large_function() {
        // 几十行或上百行代码
        // 不应该标记为inline
    }
    
    // b) 递归函数
    int recursive_function(int n) {
        if (n <= 1) return 1;
        return n * recursive_function(n - 1);
    }
    
    // c) 包含循环的函数
    void process_array(int* arr, int size) {
        for (int i = 0; i < size; ++i) {
            // 复杂处理
        }
    }
    
    // d) 虚函数
    virtual void virtual_function() {
        // 虚函数通常不能inline,因为需要动态绑定
    }
    
private:
    int value_ = 0;
};

// 2. inline函数的可见性问题
// 头文件中:
namespace Math {
    inline int add(int a, int b) {
        return a + b;
    }
    
    inline int multiply(int a, int b) {
        return a * b;
    }
}

// 多个源文件包含这个头文件时,不会产生重复定义错误
// 因为inline函数具有外部链接性

// 3. inline变量的使用(C++17)
class AppConfig {
public:
    // inline静态成员变量(C++17)
    inline static const std::string app_name = "MyApplication";
    inline static const int max_connections = 100;
    inline static const double pi = 3.141592653589793;
    
    // inline静态成员函数
    inline static const std::string& get_version() {
        static const std::string version = "1.0.0";
        return version;
    }
};

// 4. 性能测试:inline vs 非inline
#include <chrono>

class PerformanceTest {
public:
    // 标记为inline
    inline int inline_multiply(int a, int b) {
        return a * b;
    }
    
    // 不标记为inline(但编译器可能仍会inline)
    int noninline_multiply(int a, int b) {
        return a * b;
    }
    
    void run_test() {
        const int iterations = 100000000;
        volatile int result = 0;  // 防止优化
        
        // 测试inline版本
        auto start = std::chrono::high_resolution_clock::now();
        for (int i = 0; i < iterations; ++i) {
            result = inline_multiply(i, i + 1);
        }
        auto end = std::chrono::high_resolution_clock::now();
        auto inline_duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
        
        // 测试非inline版本
        start = std::chrono::high_resolution_clock::now();
        for (int i = 0; i < iterations; ++i) {
            result = noninline_multiply(i, i + 1);
        }
        end = std::chrono::high_resolution_clock::now();
        auto noninline_duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
        
        std::cout << "inline版本: " << inline_duration.count() << "ms" << std::endl;
        std::cout << "非inline版本: " << noninline_duration.count() << "ms" << std::endl;
        std::cout << "性能差异: " 
                  << (noninline_duration.count() * 100.0 / inline_duration.count() - 100) 
                  << "%" << std::endl;
        
        // 注意:现代编译器很智能,可能都会inline
        // 实际差异可能很小
    }
};

// 5. inline与模板
template<typename Container>
class ContainerUtils {
public:
    // 模板函数通常定义在头文件中,隐式inline
    static typename Container::value_type 
    sum(const Container& container) {
        typename Container::value_type total = 0;
        for (const auto& item : container) {
            total += item;
        }
        return total;
    }
    
    template<typename Predicate>
    static bool all_of(const Container& container, Predicate pred) {
        for (const auto& item : container) {
            if (!pred(item)) return false;
        }
        return true;
    }
};

// 6. 实际项目中的inline策略
class ProjectGuidelines {
public:
    // 策略1:在类定义中实现的成员函数默认inline
    class Point {
    public:
        Point(int x, int y) : x_(x), y_(y) {}
        
        int x() const { return x_; }  // 隐式inline
        int y() const { return y_; }  // 隐式inline
        
        void set_x(int x) { x_ = x; }  // 隐式inline
        void set_y(int y) { y_ = y; }  // 隐式inline
        
    private:
        int x_, y_;
    };
    
    // 策略2:短小的自由函数标记为inline
    inline int clamp(int value, int min, int max) {
        return (value < min) ? min : (value > max) ? max : value;
    }
    
    inline float lerp(float a, float b, float t) {
        return a + t * (b - a);
    }
    
    // 策略3:模板函数放在头文件中
    template<typename T>
    T min(T a, T b) {
        return a < b ? a : b;
    }
    
    // 策略4:复杂的函数实现放在源文件中
    void complex_algorithm(std::vector<int>& data);
};

int main() {
    std::cout << "=== inline最佳实践示例 ===" << std::endl;
    
    // 使用inline变量(C++17)
    std::cout << "应用名称: " << AppConfig::app_name << std::endl;
    std::cout << "最大连接数: " << AppConfig::max_connections << std::endl;
    std::cout << "版本: " << AppConfig::get_version() << std::endl;
    std::cout << "PI: " << AppConfig::pi << std::endl;
    
    // 使用数学函数
    std::cout << "45度 = " << InlineGuidelines::degrees_to_radians(45) << " 弧度" << std::endl;
    
    // 检查2的幂
    std::cout << "8是2的幂? " << (InlineGuidelines::is_power_of_two(8) ? "是" : "否") << std::endl;
    std::cout << "10是2的幂? " << (InlineGuidelines::is_power_of_two(10) ? "是" : "否") << std::endl;
    
    // 容器工具
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    std::cout << "总和: " << ContainerUtils<std::vector<int>>::sum(numbers) << std::endl;
    
    bool all_positive = ContainerUtils<std::vector<int>>::all_of(
        numbers, [](int x) { return x > 0; });
    std::cout << "所有数都大于0? " << (all_positive ? "是" : "否") << std::endl;
    
    // 项目指南示例
    ProjectGuidelines::Point p(10, 20);
    std::cout << "点坐标: (" << p.x() << ", " << p.y() << ")" << std::endl;
    
    std::cout << "clamp(15, 0, 10) = " << ProjectGuidelines::clamp(15, 0, 10) << std::endl;
    std::cout << "lerp(0, 10, 0.5) = " << ProjectGuidelines::lerp(0, 10, 0.5) << std::endl;
    std::cout << "min(5, 3) = " << ProjectGuidelines::min(5, 3) << std::endl;
    
    // 性能测试
    std::cout << "\n=== 性能测试 ===" << std::endl;
    PerformanceTest test;
    test.run_test();
    
    return 0;
}

七、更安全的空指针:nullptr

7.1 NULL的问题和nullptr的解决方案

cpp 复制代码
#include <iostream>
#include <cstddef>  // 定义NULL

// C语言中的NULL问题
void null_problems_demo() {
    std::cout << "=== NULL的问题 ===" << std::endl;
    
    // NULL在C++中通常定义为0或0L
    #ifdef __cplusplus
        std::cout << "C++中NULL的定义: " 
                  << (NULL == 0 ? "0" : "0L") << std::endl;
    #endif
    
    // 问题1:类型不明确
    void func(int x) {
        std::cout << "调用func(int): " << x << std::endl;
    }
    
    void func(char* ptr) {
        std::cout << "调用func(char*): " << (ptr ? "非空" : "空") << std::endl;
    }
    
    // 在C++中,NULL是整数0,而不是指针
    func(NULL);  // 调用func(int),而不是func(char*)
    
    // 问题2:模板推导问题
    template<typename T>
    void process(T* ptr) {
        std::cout << "处理指针" << std::endl;
    }
    
    template<typename T>
    void process(int value) {
        std::cout << "处理整数" << std::endl;
    }
    
    process<char>(NULL);  // 应该调用指针版本,但NULL是整数
    
    std::cout << std::endl;
}

// nullptr的解决方案
void nullptr_solution_demo() {
    std::cout << "=== nullptr的解决方案 ===" << std::endl;
    
    // nullptr是C++11引入的空指针字面量
    void func(int x) {
        std::cout << "调用func(int): " << x << std::endl;
    }
    
    void func(char* ptr) {
        std::cout << "调用func(char*): " << (ptr ? "非空" : "空") << std::endl;
    }
    
    void func(std::nullptr_t) {
        std::cout << "调用func(nullptr_t)" << std::endl;
    }
    
    // 明确调用指针版本
    func(nullptr);  // 调用func(char*)或func(nullptr_t)
    func(0);        // 调用func(int)
    
    // nullptr的类型是std::nullptr_t
    std::nullptr_t null_value = nullptr;
    func(null_value);  // 调用func(nullptr_t)
    
    std::cout << std::endl;
}

// 模板编程中的nullptr
template<typename T>
class SmartPointer {
private:
    T* ptr_;
    
public:
    // 构造函数
    explicit SmartPointer(T* ptr = nullptr) : ptr_(ptr) {
        std::cout << "创建SmartPointer" << std::endl;
    }
    
    // 析构函数
    ~SmartPointer() {
        delete ptr_;
        std::cout << "销毁SmartPointer" << std::endl;
    }
    
    // 检查是否为空
    bool is_null() const {
        return ptr_ == nullptr;
    }
    
    // 重载bool转换
    explicit operator bool() const {
        return ptr_ != nullptr;
    }
    
    // 重载解引用运算符
    T& operator*() const {
        if (!ptr_) {
            throw std::runtime_error("解引用空指针");
        }
        return *ptr_;
    }
    
    T* operator->() const {
        if (!ptr_) {
            throw std::runtime_error("访问空指针成员");
        }
        return ptr_;
    }
    
    // 删除拷贝操作
    SmartPointer(const SmartPointer&) = delete;
    SmartPointer& operator=(const SmartPointer&) = delete;
    
    // 允许移动
    SmartPointer(SmartPointer&& other) noexcept : ptr_(other.ptr_) {
        other.ptr_ = nullptr;
    }
    
    SmartPointer& operator=(SmartPointer&& other) noexcept {
        if (this != &other) {
            delete ptr_;
            ptr_ = other.ptr_;
            other.ptr_ = nullptr;
        }
        return *this;
    }
};

// nullptr在不同场景的应用
class Database {
public:
    class Connection {
    public:
        virtual void connect() = 0;
        virtual void disconnect() = 0;
        virtual ~Connection() = default;
    };
    
    class Statement {
    public:
        virtual void execute(const std::string& query) = 0;
        virtual ~Statement() = default;
    };
    
    // 工厂方法,返回指针可能为空
    virtual Connection* create_connection() = 0;
    virtual Statement* prepare_statement(const std::string& query) = 0;
    
    virtual ~Database() = default;
};

// 现代C++中的空指针用法
void modern_nullptr_usage() {
    std::cout << "=== 现代C++中的nullptr ===" << std::endl;
    
    // 1. 初始化指针
    int* ptr1 = nullptr;        // 推荐
    char* ptr2 = nullptr;       // 推荐
    double* ptr3 = nullptr;     // 推荐
    
    // 2. 与智能指针一起使用
    std::unique_ptr<int> smart_ptr1 = nullptr;
    std::shared_ptr<double> smart_ptr2 = nullptr;
    std::weak_ptr<char> smart_ptr3 = nullptr;
    
    // 3. 在条件语句中
    int* data_ptr = nullptr;
    
    if (data_ptr == nullptr) {
        std::cout << "指针为空" << std::endl;
    }
    
    if (!data_ptr) {  // 等价写法
        std::cout << "指针为空(简写)" << std::endl;
    }
    
    // 4. 作为函数返回值
    auto find_value = [](const std::vector<int>& vec, int target) -> int* {
        for (auto& item : vec) {
            if (item == target) {
                return &item;
            }
        }
        return nullptr;  // 没找到
    };
    
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    int* found = find_value(numbers, 3);
    
    if (found != nullptr) {
        std::cout << "找到值: " << *found << std::endl;
    }
    
    // 5. 与auto一起使用
    auto ptr4 = nullptr;  // ptr4的类型是std::nullptr_t
    // auto ptr5: int* = nullptr;  // 明确类型
    
    std::cout << std::endl;
}

// nullptr的类型安全特性
void type_safety_demo() {
    std::cout << "=== nullptr的类型安全 ===" << std::endl;
    
    // nullptr不能转换为整数
    // int x = nullptr;  // 错误:不能将nullptr转换为int
    
    // 但可以显式转换为布尔值
    bool b = (nullptr == nullptr);  // true
    std::cout << "nullptr == nullptr: " << std::boolalpha << b << std::endl;
    
    // nullptr可以转换为任何指针类型
    int* int_ptr = nullptr;
    char* char_ptr = nullptr;
    void* void_ptr = nullptr;
    
    // nullptr有自己的类型:std::nullptr_t
    std::nullptr_t null_val = nullptr;
    
    // 可以重载接受nullptr_t的函数
    void process(int* ptr) {
        std::cout << "处理int指针" << std::endl;
    }
    
    void process(std::nullptr_t) {
        std::cout << "处理nullptr" << std::endl;
    }
    
    process(nullptr);    // 调用process(nullptr_t)
    process(int_ptr);    // 调用process(int*)
    
    std::cout << std::endl;
}

// 实际工程中的nullptr应用
class ResourceManager {
private:
    class Resource {
    public:
        Resource() { std::cout << "创建资源" << std::endl; }
        ~Resource() { std::cout << "销毁资源" << std::endl; }
        
        void use() { std::cout << "使用资源" << std::endl; }
    };
    
    Resource* resource_ = nullptr;
    
public:
    ResourceManager() = default;
    
    ~ResourceManager() {
        release();
    }
    
    // 获取资源(延迟初始化)
    Resource* get_resource() {
        if (resource_ == nullptr) {
            resource_ = new Resource();
        }
        return resource_;
    }
    
    // 释放资源
    void release() {
        if (resource_ != nullptr) {
            delete resource_;
            resource_ = nullptr;  // 重要:设置为nullptr避免悬空指针
        }
    }
    
    // 检查是否有资源
    bool has_resource() const {
        return resource_ != nullptr;
    }
    
    // 重置资源
    void reset(Resource* new_resource = nullptr) {
        release();
        resource_ = new_resource;
    }
    
    // 移动语义
    ResourceManager(ResourceManager&& other) noexcept 
        : resource_(other.resource_) {
        other.resource_ = nullptr;
    }
    
    ResourceManager& operator=(ResourceManager&& other) noexcept {
        if (this != &other) {
            release();
            resource_ = other.resource_;
            other.resource_ = nullptr;
        }
        return *this;
    }
    
    // 删除拷贝
    ResourceManager(const ResourceManager&) = delete;
    ResourceManager& operator=(const ResourceManager&) = delete;
};

// nullptr在模板元编程中的应用
template<typename T>
struct TypeInfo {
    static const char* name() {
        return "unknown";
    }
};

template<>
struct TypeInfo<int> {
    static const char* name() {
        return "int";
    }
};

template<>
struct TypeInfo<std::nullptr_t> {
    static const char* name() {
        return "nullptr_t";
    }
};

template<typename T>
void print_type() {
    std::cout << "类型: " << TypeInfo<T>::name() << std::endl;
}

int main() {
    null_problems_demo();
    nullptr_solution_demo();
    modern_nullptr_usage();
    type_safety_demo();
    
    std::cout << "=== 资源管理器示例 ===" << std::endl;
    {
        ResourceManager manager;
        
        std::cout << "有资源吗? " << (manager.has_resource() ? "是" : "否") << std::endl;
        
        auto* res = manager.get_resource();
        res->use();
        
        std::cout << "有资源吗? " << (manager.has_resource() ? "是" : "否") << std::endl;
        
        manager.release();
        std::cout << "有资源吗? " << (manager.has_resource() ? "是" : "否") << std::endl;
        
        // 使用reset
        manager.reset(new ResourceManager::Resource());
        
        // 移动语义
        ResourceManager manager2 = std::move(manager);
        std::cout << "移动后,manager有资源吗? " 
                  << (manager.has_resource() ? "是" : "否") << std::endl;
    } // 自动释放资源
    
    std::cout << "\n=== 模板元编程中的nullptr ===" << std::endl;
    print_type<int>();
    print_type<std::nullptr_t>();
    
    // 使用SmartPointer
    std::cout << "\n=== 智能指针示例 ===" << std::endl;
    {
        SmartPointer<int> ptr(new int(42));
        
        if (ptr) {  // 使用bool转换
            std::cout << "值: " << *ptr << std::endl;
        }
        
        SmartPointer<int> empty_ptr(nullptr);
        std::cout << "空指针? " << (empty_ptr.is_null() ? "是" : "否") << std::endl;
        
        // 移动语义
        SmartPointer<int> moved_ptr = std::move(ptr);
        std::cout << "移动后,原指针空? " << (ptr.is_null() ? "是" : "否") << std::endl;
    }
    
    return 0;
}

7.2 从NULL迁移到nullptr

cpp 复制代码
#include <iostream>
#include <memory>
#include <cstdlib>  // 包含NULL的定义

// 旧代码库示例(使用NULL)
class LegacyCode {
public:
    // 旧的函数声明
    void* allocate_memory_old(size_t size) {
        void* ptr = std::malloc(size);
        if (ptr == NULL) {  // 使用NULL
            throw std::bad_alloc();
        }
        return ptr;
    }
    
    // 旧的重载函数
    void process_old(int value) {
        std::cout << "处理整数: " << value << std::endl;
    }
    
    void process_old(void* ptr) {
        std::cout << "处理指针: " << (ptr ? "非空" : "空") << std::endl;
    }
};

// 新代码库(使用nullptr)
class ModernCode {
public:
    // 使用nullptr的现代代码
    void* allocate_memory_new(size_t size) {
        void* ptr = std::malloc(size);
        if (ptr == nullptr) {  // 使用nullptr
            throw std::bad_alloc();
        }
        return ptr;
    }
    
    // 现代重载函数
    void process_new(int value) {
        std::cout << "处理整数: " << value << std::endl;
    }
    
    void process_new(void* ptr) {
        std::cout << "处理指针: " << (ptr ? "非空" : "空") << std::endl;
    }
    
    // 专门处理nullptr的重载
    void process_new(std::nullptr_t) {
        std::cout << "处理nullptr" << std::endl;
    }
};

// 迁移工具和技巧
class MigrationTools {
public:
    // 技巧1:使用宏进行渐进式迁移
    #ifdef USE_NULLPTR
        #define MY_NULL nullptr
    #else
        #define MY_NULL NULL
    #endif
    
    // 技巧2:类型安全的空指针包装
    template<typename T>
    class NullPointer {
    public:
        operator T*() const { return nullptr; }
        
        // 与nullptr比较
        bool operator==(std::nullptr_t) const { return true; }
        bool operator!=(std::nullptr_t) const { return false; }
        
        // 与指针比较
        template<typename U>
        bool operator==(U* ptr) const { return ptr == nullptr; }
        
        template<typename U>
        bool operator!=(U* ptr) const { return ptr != nullptr; }
    };
    
    // 使用示例
    template<typename T>
    static NullPointer<T> null() {
        return NullPointer<T>();
    }
    
    // 技巧3:检查代码中NULL的使用
    static void check_for_null_usage() {
        // 在大型项目中,可以使用静态分析工具
        // 或编写脚本检查NULL的使用
        std::cout << "检查NULL使用..." << std::endl;
    }
    
    // 技巧4:为旧代码提供适配器
    class LegacyAdapter {
    public:
        // 将nullptr转换为旧代码期望的形式
        static const void* to_legacy(std::nullptr_t) {
            return static_cast<const void*>(0);
        }
        
        // 将旧代码的NULL转换为nullptr
        static std::nullptr_t from_legacy(const void* ptr) {
            return ptr ? nullptr : nullptr;
        }
    };
};

// 实际迁移案例
class DatabaseConnection {
private:
    void* native_handle_ = nullptr;  // 使用nullptr初始化
    
public:
    DatabaseConnection() = default;
    
    explicit DatabaseConnection(void* handle) 
        : native_handle_(handle) {}
    
    // 旧的接口(兼容性)
    bool connect_old(const char* host, int port, void* options = NULL) {
        // 模拟连接
        if (options == NULL) {
            std::cout << "使用默认选项连接" << std::endl;
        } else {
            std::cout << "使用自定义选项连接" << std::endl;
        }
        return true;
    }
    
    // 新的接口(推荐)
    bool connect_new(const char* host, int port, void* options = nullptr) {
        // 模拟连接
        if (options == nullptr) {
            std::cout << "使用默认选项连接" << std::endl;
        } else {
            std::cout << "使用自定义选项连接" << std::endl;
        }
        return true;
    }
    
    // 检查连接是否有效
    bool is_connected() const {
        return native_handle_ != nullptr;
    }
    
    // 断开连接
    void disconnect() {
        if (native_handle_ != nullptr) {
            // 释放资源
            native_handle_ = nullptr;  // 设置为nullptr
        }
    }
    
    // 移动语义
    DatabaseConnection(DatabaseConnection&& other) noexcept
        : native_handle_(other.native_handle_) {
        other.native_handle_ = nullptr;
    }
    
    DatabaseConnection& operator=(DatabaseConnection&& other) noexcept {
        if (this != &other) {
            disconnect();
            native_handle_ = other.native_handle_;
            other.native_handle_ = nullptr;
        }
        return *this;
    }
    
    ~DatabaseConnection() {
        disconnect();
    }
    
    // 删除拷贝
    DatabaseConnection(const DatabaseConnection&) = delete;
    DatabaseConnection& operator=(const DatabaseConnection&) = delete;
};

// nullptr在现代C++特性中的应用
class ModernFeatures {
public:
    // 1. 与constexpr结合
    constexpr static std::nullptr_t get_null() {
        return nullptr;
    }
    
    // 2. 在静态断言中
    static_assert(sizeof(nullptr) == sizeof(void*), 
                  "nullptr大小应与指针相同");
    
    // 3. 在noexcept规范中
    void safe_function() noexcept(nullptr) {
        // C++17:条件性noexcept
    }
    
    // 4. 在模板元编程中
    template<typename T>
    struct IsPointer {
        static constexpr bool value = false;
    };
    
    template<typename T>
    struct IsPointer<T*> {
        static constexpr bool value = true;
    };
    
    // 5. 与decltype一起使用
    auto get_pointer_type() -> decltype(nullptr) {
        return nullptr;
    }
    
    // 6. 在lambda表达式中
    auto get_null_lambda = []() -> auto* {
        return nullptr;
    };
    
    // 7. 在可变参数模板中
    template<typename... Args>
    void process_args(Args... args) {
        // 处理参数,包括nullptr
    }
};

// 最佳实践总结
class BestPractices {
public:
    // 规则1:始终使用nullptr,而不是NULL或0
    void rule1() {
        int* ptr1 = nullptr;      // 正确
        // int* ptr2 = NULL;      // 避免
        // int* ptr3 = 0;         // 避免
    }
    
    // 规则2:使用nullptr初始化所有指针
    class Example {
        int* data_ = nullptr;     // 正确:成员初始化
        std::unique_ptr<int> ptr_ = nullptr;  // 正确:智能指针
        
    public:
        Example() = default;
        
        explicit Example(int* data) 
            : data_(data) {}      // 允许非nullptr初始化
    };
    
    // 规则3:在比较中使用nullptr
    void rule3(int* ptr) {
        if (ptr == nullptr) {     // 显式比较
            // 处理空指针
        }
        
        if (!ptr) {               // 隐式比较(等效)
            // 处理空指针
        }
    }
    
    // 规则4:使用nullptr作为默认参数
    void rule4(int* ptr = nullptr) {  // 正确
        if (ptr) {
            // 使用指针
        }
    }
    
    // 规则5:释放后立即设置为nullptr
    void rule5() {
        int* ptr = new int(42);
        
        // 使用ptr...
        
        delete ptr;
        ptr = nullptr;  // 重要:避免悬空指针
    }
    
    // 规则6:在移动操作后设置为nullptr
    class Movable {
        int* resource_ = nullptr;
        
    public:
        Movable(int* res) : resource_(res) {}
        
        Movable(Movable&& other) noexcept
            : resource_(other.resource_) {
            other.resource_ = nullptr;  // 重要:移动后置空
        }
        
        ~Movable() {
            delete resource_;
        }
    };
    
    // 规则7:在接口中使用nullptr_t表示空指针参数
    void rule7(std::nullptr_t) {
        std::cout << "专门处理nullptr" << std::endl;
    }
};

int main() {
    std::cout << "=== 从NULL迁移到nullptr ===" << std::endl;
    
    // 旧代码使用
    LegacyCode legacy;
    legacy.process_old(NULL);     // 调用process_old(int)
    legacy.process_old((void*)NULL);  // 调用process_old(void*)
    
    // 新代码使用
    ModernCode modern;
    modern.process_new(0);        // 调用process_new(int)
    modern.process_new(nullptr);  // 调用process_new(nullptr_t)或process_new(void*)
    
    // 迁移工具使用
    MigrationTools::NullPointer<int> null_int = MigrationTools::null<int>();
    int* test_ptr = null_int;  // 转换为nullptr
    
    if (test_ptr == nullptr) {
        std::cout << "NullPointer转换为nullptr" << std::endl;
    }
    
    // 数据库连接示例
    std::cout << "\n=== 数据库连接示例 ===" << std::endl;
    DatabaseConnection conn1;
    DatabaseConnection conn2;
    
    // 旧方式
    conn1.connect_old("localhost", 3306, NULL);
    
    // 新方式
    conn2.connect_new("localhost", 3306, nullptr);
    
    std::cout << "conn1已连接? " << (conn1.is_connected() ? "是" : "否") << std::endl;
    std::cout << "conn2已连接? " << (conn2.is_connected() ? "是" : "否") << std::endl;
    
    // 移动语义
    DatabaseConnection conn3 = std::move(conn2);
    std::cout << "移动后conn2已连接? " << (conn2.is_connected() ? "是" : "否") << std::endl;
    std::cout << "移动后conn3已连接? " << (conn3.is_connected() ? "是" : "否") << std::endl;
    
    // 现代特性
    std::cout << "\n=== 现代特性 ===" << std::endl;
    ModernFeatures features;
    
    constexpr auto null = ModernFeatures::get_null();
    std::cout << "编译期nullptr: " << (null == nullptr ? "是nullptr" : "不是nullptr") << std::endl;
    
    // 类型检查
    std::cout << "int*是指针类型? " 
              << (ModernFeatures::IsPointer<int*>::value ? "是" : "否") << std::endl;
    std::cout << "int是指针类型? " 
              << (ModernFeatures::IsPointer<int>::value ? "是" : "否") << std::endl;
    
    // 最佳实践
    std::cout << "\n=== 最佳实践 ===" << std::endl;
    BestPractices practices;
    
    int value = 42;
    practices.rule3(&value);      // 非空指针
    practices.rule3(nullptr);     // 空指针
    
    practices.rule4();            // 使用默认参数nullptr
    practices.rule4(&value);      // 传递非空指针
    
    practices.rule7(nullptr);     // 专门处理nullptr
    
    return 0;
}

八、简单了解类:class(基础概念)

8.1 从C结构体到C++类

cpp 复制代码
#include <iostream>
#include <cstring>
#include <string>

// C语言的结构体
struct CStudent {
    char name[50];
    int age;
    float score;
};

// C语言操作结构体的函数
void CStudent_init(struct CStudent* stu, const char* name, int age, float score) {
    strncpy(stu->name, name, sizeof(stu->name) - 1);
    stu->name[sizeof(stu->name) - 1] = '\0';
    stu->age = age;
    stu->score = score;
}

void CStudent_print(const struct CStudent* stu) {
    printf("姓名: %s, 年龄: %d, 成绩: %.1f\n", stu->name, stu->age, stu->score);
}

// C++的类
class Student {
private:
    // 私有成员变量:外部不能直接访问
    std::string name_;  // 使用std::string而不是char数组
    int age_;
    float score_;
    
public:
    // 构造函数:对象创建时自动调用
    Student(const std::string& name, int age, float score)
        : name_(name), age_(age), score_(score) {
        std::cout << "创建Student: " << name_ << std::endl;
    }
    
    // 默认构造函数
    Student() : name_("未知"), age_(0), score_(0.0f) {
        std::cout << "创建默认Student" << std::endl;
    }
    
    // 拷贝构造函数
    Student(const Student& other)
        : name_(other.name_), age_(other.age_), score_(other.score_) {
        std::cout << "拷贝Student: " << name_ << std::endl;
    }
    
    // 析构函数:对象销毁时自动调用
    ~Student() {
        std::cout << "销毁Student: " << name_ << std::endl;
    }
    
    // 公有成员函数:外部可以调用
    void print() const {
        std::cout << "姓名: " << name_ 
                  << ", 年龄: " << age_ 
                  << ", 成绩: " << score_ << std::endl;
    }
    
    // Getter方法:访问私有成员
    std::string get_name() const {
        return name_;
    }
    
    int get_age() const {
        return age_;
    }
    
    float get_score() const {
        return score_;
    }
    
    // Setter方法:修改私有成员(可以添加验证)
    void set_name(const std::string& name) {
        if (!name.empty()) {
            name_ = name;
        }
    }
    
    void set_age(int age) {
        if (age >= 0 && age <= 150) {
            age_ = age;
        }
    }
    
    void set_score(float score) {
        if (score >= 0.0f && score <= 100.0f) {
            score_ = score;
        }
    }
    
    // 成员函数可以访问私有成员
    bool is_excellent() const {
        return score_ >= 90.0f;
    }
    
    void promote() {
        age_++;
        score_ += 5.0f;  // 假设每年进步
        if (score_ > 100.0f) score_ = 100.0f;
    }
};

// 对比C和C++的方式
void compare_c_cpp() {
    std::cout << "=== C语言方式 ===" << std::endl;
    struct CStudent c_stu;
    CStudent_init(&c_stu, "张三", 20, 85.5);
    CStudent_print(&c_stu);
    
    // C语言可以直接修改结构体成员(不安全)
    c_stu.score = 120.0f;  // 无效的成绩,但编译器不会阻止
    
    std::cout << "\n=== C++方式 ===" << std::endl;
    Student stu("李四", 21, 88.5);
    stu.print();
    
    // 不能直接修改私有成员
    // stu.score_ = 120.0f;  // 编译错误:score_是私有的
    
    // 必须通过公有接口
    stu.set_score(92.5f);
    stu.print();
    
    std::cout << "是否优秀: " << (stu.is_excellent() ? "是" : "否") << std::endl;
    
    stu.promote();
    std::cout << "升级后: ";
    stu.print();
}

// 类的更多特性
class Rectangle {
private:
    double width_;
    double height_;
    
public:
    // 构造函数重载
    Rectangle() : width_(1.0), height_(1.0) {}
    
    Rectangle(double side) : width_(side), height_(side) {}
    
    Rectangle(double width, double height) 
        : width_(width), height_(height) {}
    
    // 成员函数
    double area() const {
        return width_ * height_;
    }
    
    double perimeter() const {
        return 2 * (width_ + height_);
    }
    
    // 重载运算符
    Rectangle operator+(const Rectangle& other) const {
        return Rectangle(width_ + other.width_, 
                         height_ + other.height_);
    }
    
    Rectangle operator*(double scale) const {
        return Rectangle(width_ * scale, height_ * scale);
    }
    
    // 友元函数:可以访问私有成员的非成员函数
    friend Rectangle operator*(double scale, const Rectangle& rect);
    
    // 静态成员:属于类本身,而不是对象
    static int get_count() {
        return count_;
    }
    
private:
    static int count_;  // 静态成员变量声明
};

// 静态成员定义(必须在类外定义)
int Rectangle::count_ = 0;

// 友元函数定义
Rectangle operator*(double scale, const Rectangle& rect) {
    return Rectangle(rect.width_ * scale, rect.height_ * scale);
}

// const成员函数示例
class BankAccount {
private:
    std::string owner_;
    mutable double balance_;  // mutable允许在const函数中修改
    
public:
    BankAccount(const std::string& owner, double balance)
        : owner_(owner), balance_(balance) {}
    
    // const成员函数:承诺不修改对象状态
    const std::string& get_owner() const {
        return owner_;
    }
    
    double get_balance() const {
        return balance_;
    }
    
    // 非const成员函数:可以修改对象状态
    void deposit(double amount) {
        if (amount > 0) {
            balance_ += amount;
        }
    }
    
    bool withdraw(double amount) {
        if (amount > 0 && balance_ >= amount) {
            balance_ -= amount;
            return true;
        }
        return false;
    }
    
    // const函数中修改mutable成员
    void add_interest(double rate) const {
        // 虽然函数是const,但可以修改mutable成员
        balance_ *= (1.0 + rate);
    }
};

int main() {
    compare_c_cpp();
    
    std::cout << "\n=== 矩形类示例 ===" << std::endl;
    Rectangle rect1;           // 使用默认构造函数
    Rectangle rect2(5.0);      // 使用单参数构造函数
    Rectangle rect3(3.0, 4.0); // 使用双参数构造函数
    
    std::cout << "rect1面积: " << rect1.area() << std::endl;
    std::cout << "rect2面积: " << rect2.area() << std::endl;
    std::cout << "rect3面积: " << rect3.area() << std::endl;
    std::cout << "rect3周长: " << rect3.perimeter() << std::endl;
    
    // 运算符重载
    Rectangle rect4 = rect2 + rect3;
    std::cout << "rect2 + rect3面积: " << rect4.area() << std::endl;
    
    Rectangle rect5 = rect3 * 2.0;
    std::cout << "rect3 * 2面积: " << rect5.area() << std::endl;
    
    Rectangle rect6 = 3.0 * rect3;
    std::cout << "3 * rect3面积: " << rect6.area() << std::endl;
    
    // 静态成员
    std::cout << "矩形计数: " << Rectangle::get_count() << std::endl;
    
    std::cout << "\n=== 银行账户示例 ===" << std::endl;
    BankAccount account("张三", 1000.0);
    
    std::cout << "账户所有人: " << account.get_owner() << std::endl;
    std::cout << "账户余额: " << account.get_balance() << std::endl;
    
    account.deposit(500.0);
    std::cout << "存款后余额: " << account.get_balance() << std::endl;
    
    if (account.withdraw(300.0)) {
        std::cout << "取款成功,余额: " << account.get_balance() << std::endl;
    }
    
    // const对象只能调用const成员函数
    const BankAccount& const_account = account;
    std::cout << "const引用获取余额: " << const_account.get_balance() << std::endl;
    
    // mutable成员可以在const函数中修改
    const_account.add_interest(0.05);
    std::cout << "添加利息后余额: " << account.get_balance() << std::endl;
    
    return 0;
}

8.2 类的封装、继承和多态基础

cpp 复制代码
#include <iostream>
#include <string>
#include <vector>
#include <memory>

// 1. 封装:隐藏实现细节,提供公有接口
class Employee {
private:
    std::string name_;
    int id_;
    double salary_;
    
protected:
    // 保护成员:派生类可以访问,外部不能访问
    std::string department_;
    
public:
    Employee(const std::string& name, int id, double salary, 
             const std::string& department)
        : name_(name), id_(id), salary_(salary), department_(department) {}
    
    virtual ~Employee() = default;
    
    // 公有接口
    virtual void work() const {
        std::cout << name_ << "正在工作..." << std::endl;
    }
    
    virtual void print_info() const {
        std::cout << "员工信息:" << std::endl;
        std::cout << "  姓名: " << name_ << std::endl;
        std::cout << "  工号: " << id_ << std::endl;
        std::cout << "  部门: " << department_ << std::endl;
        std::cout << "  薪水: " << salary_ << std::endl;
    }
    
    // Getter和Setter
    std::string get_name() const { return name_; }
    int get_id() const { return id_; }
    double get_salary() const { return salary_; }
    
    void set_salary(double salary) {
        if (salary > 0) {
            salary_ = salary;
        }
    }
    
    // 静态成员
    static int get_total_employees() {
        return total_employees_;
    }
    
private:
    static int total_employees_;
};

int Employee::total_employees_ = 0;

// 2. 继承:创建新类,复用现有类的特性
class Manager : public Employee {
private:
    int team_size_;
    std::vector<Employee*> team_;
    
public:
    Manager(const std::string& name, int id, double salary,
            const std::string& department, int team_size)
        : Employee(name, id, salary, department), team_size_(team_size) {}
    
    // 重写基类虚函数(多态)
    void work() const override {
        std::cout << get_name() << "正在管理团队..." << std::endl;
    }
    
    void print_info() const override {
        Employee::print_info();  // 调用基类版本
        std::cout << "  团队人数: " << team_size_ << std::endl;
        std::cout << "  角色: 经理" << std::endl;
    }
    
    // 特有的功能
    void add_to_team(Employee* employee) {
        if (team_.size() < static_cast<size_t>(team_size_)) {
            team_.push_back(employee);
            std::cout << employee->get_name() << "已加入团队" << std::endl;
        }
    }
    
    void hold_meeting() const {
        std::cout << get_name() << "正在召开团队会议" << std::endl;
    }
    
    // 访问保护成员
    void change_department(const std::string& new_dept) {
        department_ = new_dept;
        std::cout << get_name() << "的部门已改为: " << department_ << std::endl;
    }
};

// 3. 多态:通过基类指针/引用调用派生类函数
class Developer : public Employee {
private:
    std::string programming_language_;
    
public:
    Developer(const std::string& name, int id, double salary,
              const std::string& department, const std::string& language)
        : Employee(name, id, salary, department), 
          programming_language_(language) {}
    
    void work() const override {
        std::cout << get_name() << "正在用" << programming_language_ 
                  << "编程..." << std::endl;
    }
    
    void print_info() const override {
        Employee::print_info();
        std::cout << "  编程语言: " << programming_language_ << std::endl;
        std::cout << "  角色: 开发人员" << std::endl;
    }
    
    void debug_code() const {
        std::cout << get_name() << "正在调试代码..." << std::endl;
    }
};

// 4. 抽象类:包含纯虚函数的类
class Shape {
public:
    virtual ~Shape() = default;
    
    // 纯虚函数:必须在派生类中实现
    virtual double area() const = 0;
    virtual double perimeter() const = 0;
    virtual void draw() const = 0;
    
    // 普通虚函数:可以有默认实现
    virtual void scale(double factor) {
        std::cout << "缩放图形,因子: " << factor << std::endl;
    }
    
    // 非虚函数:不能在派生类中重写
    void print_info() const {
        std::cout << "面积: " << area() 
                  << ", 周长: " << perimeter() << std::endl;
    }
};

// 具体派生类
class Circle : public Shape {
private:
    double radius_;
    
public:
    explicit Circle(double radius) : radius_(radius) {}
    
    double area() const override {
        return 3.141592653589793 * radius_ * radius_;
    }
    
    double perimeter() const override {
        return 2 * 3.141592653589793 * radius_;
    }
    
    void draw() const override {
        std::cout << "绘制圆形,半径: " << radius_ << std::endl;
    }
    
    void scale(double factor) override {
        radius_ *= factor;
        Shape::scale(factor);  // 调用基类实现
    }
};

class Rectangle : public Shape {
private:
    double width_, height_;
    
public:
    Rectangle(double width, double height) 
        : width_(width), height_(height) {}
    
    double area() const override {
        return width_ * height_;
    }
    
    double perimeter() const override {
        return 2 * (width_ + height_);
    }
    
    void draw() const override {
        std::cout << "绘制矩形,宽度: " << width_ 
                  << ", 高度: " << height_ << std::endl;
    }
    
    void scale(double factor) override {
        width_ *= factor;
        height_ *= factor;
    }
};

// 5. 组合:包含其他类对象作为成员
class Project {
private:
    std::string name_;
    Manager* manager_;
    std::vector<Developer*> developers_;
    std::vector<std::unique_ptr<Shape>> designs_;
    
public:
    Project(const std::string& name, Manager* manager)
        : name_(name), manager_(manager) {}
    
    void add_developer(Developer* dev) {
        developers_.push_back(dev);
        std::cout << dev->get_name() << "已加入项目" << std::endl;
    }
    
    void add_design(std::unique_ptr<Shape> shape) {
        designs_.push_back(std::move(shape));
    }
    
    void run() const {
        std::cout << "\n=== 运行项目: " << name_ << " ===" << std::endl;
        
        // 经理工作
        if (manager_) {
            manager_->work();
            manager_->hold_meeting();
        }
        
        // 开发人员工作
        std::cout << "\n开发团队工作:" << std::endl;
        for (const auto& dev : developers_) {
            dev->work();
            dev->debug_code();
        }
        
        // 设计工作
        std::cout << "\n设计工作:" << std::endl;
        for (const auto& design : designs_) {
            design->draw();
            design->print_info();
        }
        
        std::cout << "项目完成!" << std::endl;
    }
    
    double total_design_area() const {
        double total = 0.0;
        for (const auto& design : designs_) {
            total += design->area();
        }
        return total;
    }
};

// 6. 工厂模式:创建对象的接口
class EmployeeFactory {
public:
    static std::unique_ptr<Employee> create_employee(
        const std::string& type,
        const std::string& name,
        int id,
        double salary,
        const std::string& department,
        const std::string& extra = "") {
        
        if (type == "manager") {
            int team_size = extra.empty() ? 5 : std::stoi(extra);
            return std::make_unique<Manager>(name, id, salary, department, team_size);
        }
        else if (type == "developer") {
            std::string language = extra.empty() ? "C++" : extra;
            return std::make_unique<Developer>(name, id, salary, department, language);
        }
        else if (type == "employee") {
            return std::make_unique<Employee>(name, id, salary, department);
        }
        
        return nullptr;
    }
};

int main() {
    std::cout << "=== 面向对象编程示例 ===" << std::endl;
    
    // 创建员工
    Manager manager("王经理", 1001, 15000.0, "技术部", 8);
    Developer dev1("张开发", 1002, 12000.0, "技术部", "C++");
    Developer dev2("李开发", 1003, 11000.0, "技术部", "Python");
    
    // 多态演示
    std::cout << "\n=== 多态演示 ===" << std::endl;
    std::vector<Employee*> employees = {&manager, &dev1, &dev2};
    
    for (const auto& emp : employees) {
        emp->work();         // 动态绑定,调用实际类型的work()
        emp->print_info();   // 动态绑定
        std::cout << std::endl;
    }
    
    // 使用基类指针
    Employee* emp_ptr = &dev1;
    emp_ptr->work();  // 调用Developer::work()
    
    // 不能通过基类指针调用派生类特有函数
    // emp_ptr->debug_code();  // 错误
    
    // 需要向下转型(不安全)
    if (auto dev_ptr = dynamic_cast<Developer*>(emp_ptr)) {
        dev_ptr->debug_code();
    }
    
    // 抽象类和具体类
    std::cout << "\n=== 抽象类演示 ===" << std::endl;
    std::vector<std::unique_ptr<Shape>> shapes;
    shapes.push_back(std::make_unique<Circle>(5.0));
    shapes.push_back(std::make_unique<Rectangle>(4.0, 6.0));
    
    for (const auto& shape : shapes) {
        shape->draw();
        shape->print_info();
        
        // 缩放
        shape->scale(1.5);
        shape->print_info();
        std::cout << std::endl;
    }
    
    // 项目组合示例
    std::cout << "\n=== 项目组合演示 ===" << std::endl;
    Project project("新一代AI系统", &manager);
    project.add_developer(&dev1);
    project.add_developer(&dev2);
    
    project.add_design(std::make_unique<Circle>(10.0));
    project.add_design(std::make_unique<Rectangle>(20.0, 30.0));
    
    project.run();
    std::cout << "总设计面积: " << project.total_design_area() << std::endl;
    
    // 工厂模式示例
    std::cout << "\n=== 工厂模式演示 ===" << std::endl;
    auto emp1 = EmployeeFactory::create_employee(
        "manager", "赵总", 2001, 20000.0, "管理部", "10");
    
    auto emp2 = EmployeeFactory::create_employee(
        "developer", "钱工", 2002, 13000.0, "研发部", "Java");
    
    if (emp1) emp1->print_info();
    if (emp2) emp2->print_info();
    
    std::cout << "\n=== 封装演示 ===" << std::endl;
    // 封装的好处:控制对数据的访问
    Employee emp("孙员工", 3001, 8000.0, "市场部");
    
    // 不能直接访问私有成员
    // emp.salary_ = 1000000.0;  // 错误
    
    // 必须通过公有接口
    emp.set_salary(9000.0);  // 可以添加验证逻辑
    std::cout << "新薪水: " << emp.get_salary() << std::endl;
    
    // 尝试设置无效薪水
    emp.set_salary(-1000.0);  // 会被拒绝
    std::cout << "无效设置后薪水: " << emp.get_salary() << std::endl;
    
    return 0;
}

8.3 现代C++类特性

cpp 复制代码
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <algorithm>

// 1. 默认和删除的特殊成员函数
class ModernClass {
private:
    std::string name_;
    std::unique_ptr<int[]> data_;
    size_t size_;
    
public:
    // 默认构造函数
    ModernClass() = default;
    
    // 自定义构造函数
    explicit ModernClass(const std::string& name, size_t size = 10)
        : name_(name), data_(std::make_unique<int[]>(size)), size_(size) {
        std::fill(data_.get(), data_.get() + size_, 0);
    }
    
    // 拷贝构造函数(删除)
    ModernClass(const ModernClass&) = delete;
    
    // 拷贝赋值运算符(删除)
    ModernClass& operator=(const ModernClass&) = delete;
    
    // 移动构造函数(默认)
    ModernClass(ModernClass&&) noexcept = default;
    
    // 移动赋值运算符(默认)
    ModernClass& operator=(ModernClass&&) noexcept = default;
    
    // 析构函数(默认)
    ~ModernClass() = default;
    
    // 自定义成员函数
    void set_value(size_t index, int value) {
        if (index < size_) {
            data_[index] = value;
        }
    }
    
    int get_value(size_t index) const {
        return (index < size_) ? data_[index] : 0;
    }
    
    const std::string& name() const { return name_; }
    size_t size() const { return size_; }
    
    // 运算符重载
    ModernClass operator+(const ModernClass& other) const {
        size_t new_size = std::max(size_, other.size_);
        ModernClass result(name_ + "+" + other.name_, new_size);
        
        for (size_t i = 0; i < new_size; ++i) {
            int val1 = (i < size_) ? data_[i] : 0;
            int val2 = (i < other.size_) ? other.data_[i] : 0;
            result.set_value(i, val1 + val2);
        }
        
        return result;
    }
};

// 2. 委托构造函数
class Configuration {
private:
    std::string host_;
    int port_;
    int timeout_;
    bool use_ssl_;
    
public:
    // 委托构造函数
    Configuration() : Configuration("localhost", 80, 30, false) {}
    
    Configuration(const std::string& host) : Configuration(host, 80, 30, false) {}
    
    Configuration(const std::string& host, int port) 
        : Configuration(host, port, 30, false) {}
    
    // 目标构造函数
    Configuration(const std::string& host, int port, int timeout, bool use_ssl)
        : host_(host), port_(port), timeout_(timeout), use_ssl_(use_ssl) {
        std::cout << "创建配置: " << host_ << ":" << port_ << std::endl;
    }
    
    void print() const {
        std::cout << "配置详情:" << std::endl;
        std::cout << "  主机: " << host_ << std::endl;
        std::cout << "  端口: " << port_ << std::endl;
        std::cout << "  超时: " << timeout_ << "秒" << std::endl;
        std::cout << "  SSL: " << (use_ssl_ ? "启用" : "禁用") << std::endl;
    }
};

// 3. 显式构造函数
class StringWrapper {
private:
    std::string data_;
    
public:
    // 允许隐式转换
    StringWrapper(const char* str) : data_(str) {}
    
    // 显式构造函数:禁止隐式转换
    explicit StringWrapper(int length) : data_(length, ' ') {}
    
    const std::string& get() const { return data_; }
};

void process_string(const StringWrapper& str) {
    std::cout << "处理字符串: " << str.get() << std::endl;
}

// 4. final类和方法
class BaseClass {
public:
    virtual void method1() {
        std::cout << "BaseClass::method1" << std::endl;
    }
    
    // final虚函数:不能被子类重写
    virtual void method2() final {
        std::cout << "BaseClass::method2 (final)" << std::endl;
    }
};

class DerivedClass final : public BaseClass {  // final类:不能被继承
public:
    void method1() override {
        std::cout << "DerivedClass::method1" << std::endl;
    }
    
    // 不能重写method2,因为它是final的
    // void method2() override { ... }  // 错误
};

// 5. override关键字
class Shape {
public:
    virtual ~Shape() = default;
    
    virtual void draw() const {
        std::cout << "绘制形状" << std::endl;
    }
    
    virtual double area() const = 0;
    
    // 重载虚函数
    virtual void scale(double factor) {
        std::cout << "缩放: " << factor << std::endl;
    }
    
    virtual void scale(double x, double y) {
        std::cout << "缩放: (" << x << ", " << y << ")" << std::endl;
    }
};

class Circle : public Shape {
private:
    double radius_;
    
public:
    explicit Circle(double radius) : radius_(radius) {}
    
    // 使用override确保正确重写
    void draw() const override {
        std::cout << "绘制圆形,半径: " << radius_ << std::endl;
    }
    
    double area() const override {
        return 3.141592653589793 * radius_ * radius_;
    }
    
    // 重写一个重载版本
    void scale(double factor) override {
        radius_ *= factor;
        std::cout << "圆形缩放后半径: " << radius_ << std::endl;
    }
    
    // 可以添加新函数
    double circumference() const {
        return 2 * 3.141592653589793 * radius_;
    }
};

// 6. 类内成员初始化
class GameCharacter {
private:
    // 类内成员初始化(C++11)
    std::string name_ = "未知角色";
    int health_ = 100;
    int level_ = 1;
    double experience_ = 0.0;
    
    // const成员也可以在类内初始化
    const int max_health_ = 1000;
    
    // 静态成员类内初始化(C++17)
    inline static int total_characters_ = 0;
    
public:
    // 委托构造函数可以使用类内初始值
    GameCharacter() {
        total_characters_++;
    }
    
    GameCharacter(const std::string& name) : name_(name) {
        total_characters_++;
    }
    
    GameCharacter(const std::string& name, int health, int level)
        : name_(name), health_(health), level_(level) {
        total_characters_++;
    }
    
    ~GameCharacter() {
        total_characters_--;
    }
    
    void print() const {
        std::cout << "角色信息:" << std::endl;
        std::cout << "  名称: " << name_ << std::endl;
        std::cout << "  生命值: " << health_ << "/" << max_health_ << std::endl;
        std::cout << "  等级: " << level_ << std::endl;
        std::cout << "  经验: " << experience_ << std::endl;
    }
    
    static int get_total_characters() {
        return total_characters_;
    }
};

// 7. 结构化绑定(C++17)
class Point3D {
private:
    double x_, y_, z_;
    
public:
    Point3D(double x, double y, double z) : x_(x), y_(y), z_(z) {}
    
    // 使类支持结构化绑定
    template<size_t Index>
    auto get() const {
        if constexpr (Index == 0) return x_;
        else if constexpr (Index == 1) return y_;
        else if constexpr (Index == 2) return z_;
    }
    
    double x() const { return x_; }
    double y() const { return y_; }
    double z() const { return z_; }
};

// 为Point3D特化std::tuple_size和std::tuple_element
namespace std {
    template<>
    struct tuple_size<Point3D> : integral_constant<size_t, 3> {};
    
    template<size_t Index>
    struct tuple_element<Index, Point3D> {
        using type = double;
    };
}

// 8. 三路比较运算符(C++20)
#include <compare>  // 需要C++20

class ModernVersion {
private:
    int major_, minor_, patch_;
    
public:
    ModernVersion(int major = 1, int minor = 0, int patch = 0)
        : major_(major), minor_(minor), patch_(patch) {}
    
    // 三路比较运算符(C++20)
    auto operator<=>(const ModernVersion& other) const = default;
    
    // 或者自定义比较逻辑
    /*
    auto operator<=>(const ModernVersion& other) const {
        if (auto cmp = major_ <=> other.major_; cmp != 0) return cmp;
        if (auto cmp = minor_ <=> other.minor_; cmp != 0) return cmp;
        return patch_ <=> other.patch_;
    }
    */
    
    void print() const {
        std::cout << "v" << major_ << "." << minor_ << "." << patch_ << std::endl;
    }
};

int main() {
    std::cout << "=== 现代C++类特性 ===" << std::endl;
    
    // 1. 默认和删除的特殊成员函数
    std::cout << "\n1. 默认和删除函数:" << std::endl;
    ModernClass obj1("对象1", 5);
    ModernClass obj2("对象2", 3);
    
    // 不能拷贝
    // ModernClass obj3 = obj1;  // 错误:拷贝构造函数已删除
    
    // 可以移动
    ModernClass obj3 = std::move(obj1);
    std::cout << "移动后obj1大小: " << obj1.size() << std::endl;
    std::cout << "obj3大小: " << obj3.size() << std::endl;
    
    // 运算符重载
    ModernClass sum = obj2 + obj3;
    std::cout << "求和对象名称: " << sum.name() << std::endl;
    
    // 2. 委托构造函数
    std::cout << "\n2. 委托构造函数:" << std::endl;
    Configuration cfg1;
    Configuration cfg2("example.com");
    Configuration cfg3("api.example.com", 443);
    Configuration cfg4("secure.example.com", 8443, 60, true);
    
    cfg1.print();
    cfg2.print();
    cfg3.print();
    cfg4.print();
    
    // 3. 显式构造函数
    std::cout << "\n3. 显式构造函数:" << std::endl;
    StringWrapper str1("Hello");  // 允许隐式转换
    StringWrapper str2(10);       // 显式构造函数
    
    process_string(str1);         // OK
    process_string("World");      // OK:隐式转换
    // process_string(20);        // 错误:不能隐式转换int到StringWrapper
    
    // 4. final类和方法
    std::cout << "\n4. final类和方法:" << std::endl;
    DerivedClass derived;
    derived.method1();
    derived.method2();  // 调用基类的final方法
    
    // 5. override关键字
    std::cout << "\n5. override关键字:" << std::endl;
    Circle circle(5.0);
    circle.draw();
    std::cout << "面积: " << circle.area() << std::endl;
    std::cout << "周长: " << circle.circumference() << std::endl;
    circle.scale(1.5);
    
    // 6. 类内成员初始化
    std::cout << "\n6. 类内成员初始化:" << std::endl;
    GameCharacter char1;
    GameCharacter char2("英雄");
    GameCharacter char3("BOSS", 500, 10);
    
    char1.print();
    char2.print();
    char3.print();
    
    std::cout << "总角色数: " << GameCharacter::get_total_characters() << std::endl;
    
    // 7. 结构化绑定(C++17)
    std::cout << "\n7. 结构化绑定:" << std::endl;
    Point3D point(1.0, 2.0, 3.0);
    
    auto [x, y, z] = point;  // 结构化绑定
    std::cout << "点坐标: (" << x << ", " << y << ", " << z << ")" << std::endl;
    
    // 8. 三路比较运算符(C++20)
    std::cout << "\n8. 三路比较运算符:" << std::endl;
    ModernVersion v1(1, 2, 3);
    ModernVersion v2(1, 2, 4);
    ModernVersion v3(2, 0, 0);
    
    std::cout << "v1: "; v1.print();
    std::cout << "v2: "; v2.print();
    std::cout << "v3: "; v3.print();
    
    // 使用三路比较
    #if __cplusplus >= 202002L
        std::cout << "v1 < v2: " << ((v1 < v2) ? "true" : "false") << std::endl;
        std::cout << "v1 <= v2: " << ((v1 <= v2) ? "true" : "false") << std::endl;
        std::cout << "v1 > v3: " << ((v1 > v3) ? "true" : "false") << std::endl;
        std::cout << "v1 == v2: " << ((v1 == v2) ? "true" : "false") << std::endl;
        std::cout << "v1 != v3: " << ((v1 != v3) ? "true" : "false") << std::endl;
    #endif
    
    return 0;
}

总结

通过本文的详细探讨,我们深入了解了C++如何解决C语言在大型项目开发中的核心痛点:

1. 命名空间(namespace)

  • 解决了全局命名冲突问题
  • 支持嵌套和别名,提供更好的模块化
  • 是现代C++模块化的基础

2. 缺省参数

  • 使函数调用更加灵活
  • 减少了代码重复
  • 需要遵循从右向左连续设置的规则

3. 引用(&)

  • 提供了更安全、更直观的指针替代方案
  • 必须初始化,不能重新绑定
  • 语法更简洁,减少错误

4. const引用

  • 提供了只读访问权限
  • 可以绑定到临时对象
  • 增强了类型安全和代码可读性

5. 指针和引用的区别

  • 引用是别名,指针是存储地址的变量
  • 引用更安全,指针更灵活
  • 根据具体场景选择合适的方式

6. inline内联函数

  • 替代了不安全的宏函数
  • 提供了类型检查和调试支持
  • 在性能关键代码中特别有用

7. nullptr

  • 解决了NULL的类型歧义问题
  • 提供了类型安全的空指针表示
  • 是现代C++中空指针的最佳实践

8. 类(class)基础

  • 引入了面向对象编程
  • 提供了封装、继承和多态的支持
  • 是现代软件工程的基础

学习建议:

  1. 循序渐进:从C语言基础开始,逐步掌握C++的新特性
  2. 实践为主:通过实际项目应用这些特性,加深理解
  3. 关注现代C++:学习C++11/14/17/20的新特性
  4. 阅读优秀代码:学习开源项目中的最佳实践
  5. 理解设计理念:不仅学习语法,更要理解C++的设计哲学

C++作为一门既支持底层系统编程又支持高级抽象的语言,在性能、灵活性和表达力之间取得了良好的平衡。掌握这些核心特性,你将能够编写出更安全、更高效、更易于维护的代码,为深入学习现代C++打下坚实的基础。

相关推荐
@淡 定2 小时前
Spring中@Autowired注解的实现原理
java·后端·spring
hgz07102 小时前
Linux服务器环境部署与JMeter压测准备
linux·服务器·jmeter
ShirleyWang0122 小时前
VMware如何导入vmdk文件
linux·数据库
charlie1145141912 小时前
如何快速在 VS2026 上使用 C++ 模块 — 完整上手指南
开发语言·c++·笔记·学习·现代c++
时空无限2 小时前
Java Buildpack Reference
java·开发语言
涛涛北京2 小时前
【强化学习实验】- 策略梯度算法
人工智能·算法
栀秋6663 小时前
深入浅出链表操作:从Dummy节点到快慢指针的实战精要
前端·javascript·算法
Lueeee.3 小时前
内核menuconfig配置实验
linux
Pyeako3 小时前
机器学习之KNN算法
人工智能·算法·机器学习