【C++ Primer】第十八章:用于大型程序的工具

用于大型程序的工具专注于 C++ 在大型项目开发中的关键特性,这些工具对于构建可维护、可扩展的复杂系统至关重要。

1. 异常处理进阶

栈展开和资源管理

#include <memory>
#include <fstream>

class DatabaseConnection {
private:
    std::string connection_string;
public:
    DatabaseConnection(const std::string& conn_str) : connection_string(conn_str) {
        std::cout << "Database connected: " << connection_string << std::endl;
    }
    
    ~DatabaseConnection() {
        std::cout << "Database disconnected: " << connection_string << std::endl;
    }
    
    void execute(const std::string& query) {
        if (query.empty()) {
            throw std::invalid_argument("Query cannot be empty");
        }
        std::cout << "Executing: " << query << std::endl;
    }
};

class FileProcessor {
private:
    std::ofstream file;
public:
    FileProcessor(const std::string& filename) : file(filename) {
        if (!file) {
            throw std::runtime_error("Cannot open file: " + filename);
        }
        std::cout << "File opened: " << filename << std::endl;
    }
    
    ~FileProcessor() {
        if (file.is_open()) {
            file.close();
            std::cout << "File closed" << std::endl;
        }
    }
    
    void write(const std::string& data) {
        file << data << std::endl;
        if (!file) {
            throw std::runtime_error("Write failed");
        }
    }
};

void stack_unwinding_demo() {
    try {
        // 使用智能指针确保资源释放
        auto db = std::make_unique<DatabaseConnection>("server=localhost;database=test");
        FileProcessor processor("output.txt");
        
        db->execute("SELECT * FROM users");
        processor.write("Processing data...");
        
        // 模拟异常
        db->execute("");  // 抛出异常
        
        processor.write("This won't be executed");
    }
    catch (const std::exception& e) {
        std::cout << "Exception caught: " << e.what() << std::endl;
        // 栈展开会自动调用 db 和 processor 的析构函数
    }
}

异常类和继承层次

// 自定义异常层次结构
class NetworkException : public std::runtime_error {
public:
    NetworkException(const std::string& msg) : std::runtime_error(msg) {}
};

class ConnectionTimeout : public NetworkException {
public:
    ConnectionTimeout() : NetworkException("Connection timeout") {}
};

class AuthenticationFailed : public NetworkException {
public:
    AuthenticationFailed() : NetworkException("Authentication failed") {}
};

class DataProcessingException : public std::runtime_error {
public:
    DataProcessingException(const std::string& msg) : std::runtime_error(msg) {}
};

void exception_hierarchy_demo() {
    try {
        // 模拟网络操作
        bool timeout_occurred = true;
        bool auth_failed = false;
        
        if (timeout_occurred) {
            throw ConnectionTimeout();
        }
        
        if (auth_failed) {
            throw AuthenticationFailed();
        }
        
        throw DataProcessingException("Data corruption detected");
    }
    catch (const ConnectionTimeout& e) {
        std::cout << "Handling timeout: " << e.what() << std::endl;
        // 重试逻辑
    }
    catch (const AuthenticationFailed& e) {
        std::cout << "Handling auth failure: " << e.what() << std::endl;
        // 重新认证逻辑
    }
    catch (const NetworkException& e) {
        std::cout << "Handling generic network error: " << e.what() << std::endl;
    }
    catch (const std::exception& e) {
        std::cout << "Handling other errors: " << e.what() << std::endl;
    }
}

noexcept 说明符

class NoExceptDemo {
public:
    // 保证不抛出异常的函数
    int simple_calculation(int x, int y) noexcept {
        return x + y;
    }
    
    // 条件性 noexcept
    template<typename T>
    void swap_values(T& a, T& b) noexcept(noexcept(T(std::move(a))) && noexcept(a.~T())) {
        T temp = std::move(a);
        a = std::move(b);
        b = std::move(temp);
    }
    
    // 可能抛出异常的函数
    void risky_operation() {
        throw std::runtime_error("This might fail");
    }
};

void noexcept_demo() {
    NoExceptDemo demo;
    
    // noexcept 函数可以在编译期检查
    static_assert(noexcept(demo.simple_calculation(1, 2)), 
                  "simple_calculation should be noexcept");
    
    std::cout << "simple_calculation is noexcept: " 
              << noexcept(demo.simple_calculation(1, 2)) << std::endl;
    std::cout << "risky_operation is noexcept: " 
              << noexcept(demo.risky_operation()) << std::endl;
}

2. 命名空间

命名空间的定义和使用

// 公司级别的命名空间组织
namespace CompanyName {
    namespace ProjectA {
        namespace Database {
            class Connection {
            public:
                void connect() { std::cout << "ProjectA DB connected" << std::endl; }
            };
            
            class Query {
            public:
                void execute() { std::cout << "ProjectA query executed" << std::endl; }
            };
        }
        
        namespace Network {
            class HttpClient {
            public:
                void request() { std::cout << "ProjectA HTTP request" << std::endl; }
            };
        }
    }
    
    namespace ProjectB {
        namespace Database {
            // 同名的类在不同的命名空间中
            class Connection {
            public:
                void connect() { std::cout << "ProjectB DB connected" << std::endl; }
            };
        }
    }
    
    // 内联命名空间(版本控制)
    namespace v1 {
        class API {
        public:
            void call() { std::cout << "v1 API called" << std::endl; }
        };
    }
    
    inline namespace v2 {  // v2 成为默认版本
        class API {
        public:
            void call() { std::cout << "v2 API called" << std::endl; }
        };
    }
}

void namespace_demo() {
    // 完全限定名
    CompanyName::ProjectA::Database::Connection conn1;
    conn1.connect();
    
    CompanyName::ProjectB::Database::Connection conn2;
    conn2.connect();
    
    // 使用别名
    namespace DB = CompanyName::ProjectA::Database;
    DB::Query query;
    query.execute();
    
    // 内联命名空间的使用
    CompanyName::API current_api;  // 默认使用 v2
    current_api.call();
    
    CompanyName::v1::API old_api;  // 显式使用 v1
    old_api.call();
}

命名空间别名和 using 声明

namespace VeryLongNamespaceName {
    namespace SubNamespace {
        class ImportantClass {
        public:
            void important_method() {
                std::cout << "Important work done" << std::endl;
            }
        };
    }
}

// 命名空间别名
namespace VLN = VeryLongNamespaceName;
namespace VSN = VeryLongNamespaceName::SubNamespace;

void using_declarations_demo() {
    // using 声明
    using VLN::SubNamespace::ImportantClass;
    ImportantClass obj1;
    obj1.important_method();
    
    // using 指令(谨慎使用)
    using namespace VLN::SubNamespace;
    ImportantClass obj2;
    obj2.important_method();
    
    // 函数内的 using 声明
    {
        using std::cout;
        using std::endl;
        cout << "Local using declarations" << endl;
    }
}

3. 多重继承

基本多重继承

class Printable {
public:
    virtual void print() const = 0;
    virtual ~Printable() = default;
};

class Serializable {
public:
    virtual std::string serialize() const = 0;
    virtual ~Serializable() = default;
};

class Drawable {
public:
    virtual void draw() const = 0;
    virtual ~Drawable() = default;
};

// 多重继承
class Circle : public Printable, public Serializable, public Drawable {
private:
    double radius;
public:
    Circle(double r) : radius(r) {}
    
    void print() const override {
        std::cout << "Circle with radius: " << radius << std::endl;
    }
    
    std::string serialize() const override {
        return "Circle:" + std::to_string(radius);
    }
    
    void draw() const override {
        std::cout << "Drawing circle (radius=" << radius << ")" << std::endl;
    }
};

void multiple_inheritance_demo() {
    Circle circle(5.0);
    
    // 通过不同接口使用对象
    circle.print();
    circle.draw();
    std::cout << "Serialized: " << circle.serialize() << std::endl;
    
    // 通过基类指针使用
    Printable* printable = &circle;
    Serializable* serializable = &circle;
    Drawable* drawable = &circle;
    
    printable->print();
    std::cout << "Via serializable: " << serializable->serialize() << std::endl;
    drawable->draw();
}

虚继承和菱形继承问题

// 菱形继承问题示例
class Animal {
protected:
    std::string name;
    int age;
public:
    Animal(const std::string& n, int a) : name(n), age(a) {}
    virtual void speak() const = 0;
    virtual ~Animal() = default;
};

class Mammal : virtual public Animal {  // 虚继承
public:
    Mammal(const std::string& n, int a) : Animal(n, a) {}
    void give_birth() const {
        std::cout << name << " gives birth to live young" << std::endl;
    }
};

class WingedAnimal : virtual public Animal {  // 虚继承
public:
    WingedAnimal(const std::string& n, int a) : Animal(n, a) {}
    void fly() const {
        std::cout << name << " is flying" << std::endl;
    }
};

// 解决菱形继承问题
class Bat : public Mammal, public WingedAnimal {
public:
    Bat(const std::string& n, int a) : Animal(n, a), Mammal(n, a), WingedAnimal(n, a) {}
    
    void speak() const override {
        std::cout << name << " says: Squeak!" << std::endl;
    }
    
    void nocturnal_activities() const {
        std::cout << name << " is active at night" << std::endl;
    }
};

void virtual_inheritance_demo() {
    Bat bat("Bruce", 3);
    
    bat.speak();           // 没有二义性
    bat.give_birth();      // 来自 Mammal
    bat.fly();             // 来自 WingedAnimal
    bat.nocturnal_activities();  // 来自 Bat
    
    // 访问共同的基类成员(没有二义性)
    std::cout << "Bat name: " << /* bat.name */ "Bruce" << std::endl;  // 实际需要访问器
}

4. 运行时类型识别(RTTI)

dynamic_cast 和 typeid

class Base {
public:
    virtual ~Base() = default;
    virtual void identify() const {
        std::cout << "I am Base" << std::endl;
    }
};

class Derived1 : public Base {
public:
    void identify() const override {
        std::cout << "I am Derived1" << std::endl;
    }
    
    void derived1_specific() const {
        std::cout << "Derived1 specific method" << std::endl;
    }
};

class Derived2 : public Base {
public:
    void identify() const override {
        std::cout << "I am Derived2" << std::endl;
    }
    
    void derived2_specific() const {
        std::cout << "Derived2 specific method" << std::endl;
    }
};

void rtti_demo() {
    std::vector<std::unique_ptr<Base>> objects;
    objects.push_back(std::make_unique<Derived1>());
    objects.push_back(std::make_unique<Derived2>());
    objects.push_back(std::make_unique<Base>());
    
    for (const auto& obj : objects) {
        // 使用 typeid 获取类型信息
        std::cout << "Type: " << typeid(*obj).name() << std::endl;
        
        // 使用 dynamic_cast 进行安全的向下转型
        if (auto d1 = dynamic_cast<Derived1*>(obj.get())) {
            std::cout << "  -> This is Derived1, calling specific method: ";
            d1->derived1_specific();
        }
        else if (auto d2 = dynamic_cast<Derived2*>(obj.get())) {
            std::cout << "  -> This is Derived2, calling specific method: ";
            d2->derived2_specific();
        }
        else {
            std::cout << "  -> This is Base or unknown derived type" << std::endl;
        }
        
        obj->identify();
        std::cout << std::endl;
    }
}

type_info 类

void type_info_demo() {
    int i = 42;
    double d = 3.14;
    std::string s = "hello";
    
    const std::type_info& ti1 = typeid(i);
    const std::type_info& ti2 = typeid(d);
    const std::type_info& ti3 = typeid(s);
    
    std::cout << "int: " << ti1.name() << std::endl;
    std::cout << "double: " << ti2.name() << std::endl;
    std::cout << "string: " << ti3.name() << std::endl;
    
    // 类型比较
    std::cout << "i and d same type: " << (ti1 == ti2) << std::endl;
    std::cout << "i and i same type: " << (ti1 == typeid(int)) << std::endl;
    
    // 哈希值(C++11)
    std::cout << "int hash: " << ti1.hash_code() << std::endl;
    std::cout << "double hash: " << ti2.hash_code() << std::endl;
}

5. 枚举类

有作用域枚举

// 传统枚举的问题
enum Color { RED, GREEN, BLUE };                    // 可能冲突
enum TrafficLight { RED, YELLOW, GREEN };           // 错误:重定义

// 枚举类解决冲突
enum class Color { RED, GREEN, BLUE };
enum class TrafficLight { RED, YELLOW, GREEN };
enum class Priority : uint8_t { LOW, MEDIUM, HIGH, CRITICAL };  // 指定底层类型

void enum_class_demo() {
    Color c = Color::RED;
    TrafficLight light = TrafficLight::GREEN;
    Priority p = Priority::HIGH;
    
    // 必须使用作用域操作符
    if (c == Color::RED) {
        std::cout << "Color is red" << std::endl;
    }
    
    // 不会隐式转换为整数
    // int color_value = c;  // 错误!
    int color_value = static_cast<int>(c);  // 需要显式转换
    std::cout << "Color value: " << color_value << std::endl;
    
    // 指定底层类型的好处
    std::cout << "Size of Priority: " << sizeof(Priority) << " bytes" << std::endl;
    std::cout << "Priority value: " << static_cast<int>(p) << std::endl;
}

枚举类的高级用法

enum class FilePermission : uint8_t {
    READ = 1 << 0,    // 00000001
    WRITE = 1 << 1,   // 00000010  
    EXECUTE = 1 << 2  // 00000100
};

// 重载操作符使枚举类更易用
constexpr FilePermission operator|(FilePermission lhs, FilePermission rhs) {
    return static_cast<FilePermission>(
        static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs));
}

constexpr FilePermission operator&(FilePermission lhs, FilePermission rhs) {
    return static_cast<FilePermission>(
        static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs));
}

constexpr bool has_permission(FilePermission perms, FilePermission check) {
    return (perms & check) == check;
}

void advanced_enum_demo() {
    FilePermission user_perms = FilePermission::READ | FilePermission::WRITE;
    
    std::cout << "User permissions: " << static_cast<int>(user_perms) << std::endl;
    
    if (has_permission(user_perms, FilePermission::READ)) {
        std::cout << "User can read" << std::endl;
    }
    
    if (!has_permission(user_perms, FilePermission::EXECUTE)) {
        std::cout << "User cannot execute" << std::endl;
    }
    
    // 添加权限
    user_perms = user_perms | FilePermission::EXECUTE;
    std::cout << "After adding execute: " << static_cast<int>(user_perms) << std::endl;
}

6. 实践项目:插件系统架构

#include <map>
#include <memory>
#include <functional>

// 插件接口
class IPlugin {
public:
    virtual ~IPlugin() = default;
    virtual std::string name() const = 0;
    virtual void initialize() = 0;
    virtual void execute() = 0;
    virtual void shutdown() = 0;
};

// 插件管理器
class PluginManager {
private:
    std::map<std::string, std::unique_ptr<IPlugin>> plugins;
    
public:
    template<typename T, typename... Args>
    void register_plugin(const std::string& name, Args&&... args) {
        static_assert(std::is_base_of_v<IPlugin, T>, 
                      "T must derive from IPlugin");
        plugins[name] = std::make_unique<T>(std::forward<Args>(args)...);
    }
    
    IPlugin* get_plugin(const std::string& name) {
        auto it = plugins.find(name);
        return it != plugins.end() ? it->second.get() : nullptr;
    }
    
    void initialize_all() {
        for (auto& [name, plugin] : plugins) {
            std::cout << "Initializing plugin: " << name << std::endl;
            plugin->initialize();
        }
    }
    
    void execute_all() {
        for (auto& [name, plugin] : plugins) {
            std::cout << "Executing plugin: " << name << std::endl;
            plugin->execute();
        }
    }
    
    void shutdown_all() {
        for (auto& [name, plugin] : plugins) {
            std::cout << "Shutting down plugin: " << name << std::endl;
            plugin->shutdown();
        }
    }
};

// 具体插件实现
class LoggerPlugin : public IPlugin {
public:
    std::string name() const override { return "Logger"; }
    
    void initialize() override {
        std::cout << "LoggerPlugin: Initializing..." << std::endl;
    }
    
    void execute() override {
        std::cout << "LoggerPlugin: Logging message..." << std::endl;
    }
    
    void shutdown() override {
        std::cout << "LoggerPlugin: Shutting down..." << std::endl;
    }
};

class NetworkPlugin : public IPlugin {
public:
    std::string name() const override { return "Network"; }
    
    void initialize() override {
        std::cout << "NetworkPlugin: Initializing connections..." << std::endl;
    }
    
    void execute() override {
        std::cout << "NetworkPlugin: Sending data..." << std::endl;
    }
    
    void shutdown() override {
        std::cout << "NetworkPlugin: Closing connections..." << std::endl;
    }
};

void plugin_system_demo() {
    PluginManager manager;
    
    // 注册插件
    manager.register_plugin<LoggerPlugin>("Logger");
    manager.register_plugin<NetworkPlugin>("Network");
    
    // 使用插件系统
    manager.initialize_all();
    std::cout << "---" << std::endl;
    manager.execute_all();
    std::cout << "---" << std::endl;
    manager.shutdown_all();
    
    // 动态获取插件
    if (auto plugin = manager.get_plugin("Logger")) {
        std::cout << "Found plugin: " << plugin->name() << std::endl;
    }
}

最佳实践总结

  1. 使用 RAII 管理资源,确保异常安全
  2. 合理组织命名空间,避免名称冲突
  3. 谨慎使用多重继承,优先使用组合
  4. 使用枚举类代替传统枚举
  5. 限制 RTTI 的使用,优先使用虚函数
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值