4.5静态成员与常对象

113 阅读3分钟

静态成员与常对象:类的高级控制

一、静态成员系统

1.1 静态成员变量

class BankAccount {
public:
    static double totalDeposit;  // 类级别存款总额
  
    BankAccount(double amount) {
        totalDeposit += amount;
    }
  
    ~BankAccount() {
        totalDeposit -= balance;
    }
  
private:
    double balance;
};

// 类外初始化静态成员
double BankAccount::totalDeposit = 0;  // 必须初始化

1.2 静态成员函数

class SystemMonitor {
    static int errorCount;
public:
    static void reportError() {  // 只能访问静态成员
        errorCount++;
        cout << "当前错误数:" << errorCount << endl;
    }
  
    void checkStatus() { /* 非静态方法 */ }
};

int SystemMonitor::errorCount = 0;

📌 静态成员特性对比表

特征静态成员普通成员
内存分配类加载时分配对象实例化时分配
访问方式ClassName::memberobject.member
生命周期程序运行期间对象生命周期
共享性所有对象共享对象独享

二、常对象控制

2.1 const成员函数

class TemperatureSensor {
    mutable int readCount;  // 可被const方法修改
    double currentTemp;
public:
    double getTemp() const {  // 承诺不修改对象状态
        readCount++;         // 允许修改mutable成员
        return currentTemp;
    }
  
    void calibrate() {       // 非const方法
        currentTemp += 0.5; 
    }
};

const TemperatureSensor ts;
ts.getTemp();    // 允许调用
// ts.calibrate(); // 错误!常对象不能调用非const方法

2.2 mutable应用场景

class CacheSystem {
    mutable string cachedData;  // 缓存数据
    mutable bool dirty;         // 缓存标志
public:
    string getData() const {
        if(dirty) {
            // 虽然const方法,仍可更新缓存
            cachedData = fetchFromDB(); 
            dirty = false;
        }
        return cachedData;
    }
};

🔐 const成员函数规则

  • 不能修改普通成员变量
  • 可以访问静态成员变量
  • 可以调用其他const成员函数
  • 可以修改mutable成员

三、单例模式实现

3.1 经典实现

class Logger {
    static Logger* instance;
    // 禁用拷贝和赋值
    Logger(const Logger&) = delete;
    Logger& operator=(const Logger&) = delete;
  
    Logger() {}  // 私有构造函数
  
public:
    static Logger& getInstance() {
        if(!instance) {
            instance = new Logger();
        }
        return *instance;
    }
  
    void log(const string& message) {
        // 日志记录实现
    }
};

// 静态成员初始化
Logger* Logger::instance = nullptr;

3.2 现代C++实现(C++11起)

class ConfigManager {
public:
    static ConfigManager& getInstance() {
        static ConfigManager instance;  // 线程安全的初始化
        return instance;
    }
  
    void loadConfig(const string& path) { /*...*/ }
  
private:
    ConfigManager() = default;
    // 自动禁用拷贝和移动操作
    ConfigManager(const ConfigManager&) = delete;
    ConfigManager& operator=(const ConfigManager&) = delete;
};

四、综合应用案例

4.1 全局计数器系统

class GlobalCounter {
    static int count;
    mutable mutex mtx;  // 允许const方法修改
public:
    void increment() const {
        lock_guard<mutex> lock(mtx);
        count++;
    }
  
    int getCount() const {
        lock_guard<mutex> lock(mtx);
        return count;
    }
  
    static void reset() {
        lock_guard<mutex> lock(mtx);
        count = 0;
    }
};

int GlobalCounter::count = 0;

五、重要规则与最佳实践

5.1 关键注意事项

  1. 静态成员初始化:必须在类外进行(除C++17的inline静态成员)
  2. 线程安全:静态数据需要考虑多线程访问
  3. 单例生命周期:需明确销毁时机,避免内存泄漏
  4. const正确性:正确使用const提高代码健壮性

5.2 设计原则

  • 对配置类、管理器类使用单例模式
  • 优先使用局部静态变量的单例实现(C++11+)
  • 为所有const方法添加const修饰符
  • 谨慎使用mutable,仅用于真正需要状态跟踪的成员

六、总结与提升

课后练习

  1. 实现线程安全的数据库连接池(单例模式)
  2. 创建学生管理系统,统计总学生数(静态成员)
  3. 设计具有缓存功能的const方法(mutable应用)

进阶话题

  • 静态成员的模板特化
  • const_cast在常对象中的使用
  • 单例模式的依赖注入实现
  • C++17的inline静态成员变量

性能提示

  • 频繁访问的静态成员考虑缓存到寄存器
  • mutable变量应尽量小且访问快速
  • 单例的懒加载/饿加载策略选择

通过合理运用静态成员和常对象控制,可以创建出高效、安全且易于维护的类结构。建议使用Valgrind等工具检测单例的内存管理,并在实际项目中结合RAII模式管理资源。记住:良好的const修饰使用可以让编译器成为你的第一道防线!