C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C++ const 与 static 类成员

C++ const 与 static变量、函数、类成员的全面解析(最新推荐)

作者:痛&快乐着

本文系统解析了C++中const与static关键字的核心用法,文章还展示了二者在单例模式等设计模式中的综合应用,并比较了C++11引入的constexpr等现代特性,正确使用这些关键字能提升代码安全性、可维护性和性能优化,感兴趣的朋友跟随小编一起看看吧

1. const 常量的初始化与赋值

基本类型 const 变量

// 必须初始化,不能先声明后赋值
const int a = 10;           // 正确:定义时初始化
const double PI = 3.14159;  // 正确
// const int b;             // 错误:未初始化常量
// b = 20;                  // 错误:不能给常量赋值

const 指针和引用

int x = 10, y = 20;
// const 指针(指向常量的指针)
const int* ptr1 = &x;       // 正确:指向的内容不可变
// *ptr1 = 30;              // 错误:不能通过ptr1修改x
ptr1 = &y;                  // 正确:指针本身可以指向其他地址
// 常量指针(指针本身是常量)
int* const ptr2 = &x;       // 正确:指针本身不可变
*ptr2 = 30;                 // 正确:可以通过ptr2修改x
// ptr2 = &y;               // 错误:ptr2是常量指针
// 指向常量的常量指针
const int* const ptr3 = &x; // 指针和指向的内容都不可变
// const 引用
const int& ref = x;         // 正确:引用不可修改其值
// ref = 40;                // 错误:不能通过ref修改x

类中的 const 成员变量

class MyClass {
private:
    const int id;           // const 成员变量
    const std::string name;
public:
    // 必须在初始化列表中初始化
    MyClass(int idVal, const std::string& nameVal) 
        : id(idVal), name(nameVal) {  // 初始化列表
        // id = idVal;      // 错误!不能在构造函数体内赋值
    }
    // 委托构造函数也要通过初始化列表
    MyClass() : MyClass(0, "Unknown") {}
};

const 成员变量的特殊情况

class AdvancedClass {
private:
    const int size = 100;           // C++11: 类内直接初始化
    static const int COUNT = 50;    // 静态常量可以在类内初始化
public:
    AdvancedClass() {}              // 使用默认值
    AdvancedClass(int s) : size(s) {} // 可以覆盖默认值
};

const 赋值规则总结

2. static 变量的使用

静态局部变量

void counterFunction() {
    static int count = 0;    // 只在第一次调用时初始化
    count++;
    std::cout << "Called " << count << " times" << std::endl;
}
// 使用
counterFunction(); // Called 1 times
counterFunction(); // Called 2 times
counterFunction(); // Called 3 times

静态成员变量

class Player {
private:
    static int totalPlayers;     // 声明
    std::string name;
    int score;
public:
    Player(const std::string& n) : name(n), score(0) {
        totalPlayers++;          // 创建对象时计数
    }
    ~Player() {
        totalPlayers--;          // 销毁对象时减计数
    }
    static int getTotalPlayers() {
        return totalPlayers;
    }
};
// 静态成员变量必须在类外定义
int Player::totalPlayers = 0;    // 定义和初始化
// 使用
Player p1("Alice");
Player p2("Bob");
std::cout << Player::getTotalPlayers(); // 输出: 2

静态常量成员变量

class MathConstants {
public:
    static const double PI;          // 需要类外定义
    static constexpr double E = 2.71828; // C++11: 可以在类内初始化
    // 整型静态常量可以在类内初始化(历史原因)
    static const int MAX_SIZE = 100;
};
// 类外定义(如果使用了取地址操作,必须定义)
const double MathConstants::PI = 3.14159;
const int MathConstants::MAX_SIZE; // 定义,不需要重复初始化

3. static 函数的使用

静态成员函数

class Utility {
private:
    static int instanceCount;
    int instanceData;           // 非静态成员
public:
    Utility() { instanceCount++; }
    // 静态成员函数
    static int getInstanceCount() {
        return instanceCount;
        // return instanceData; // 错误!不能访问非静态成员
    }
    static double calculateDistance(double x1, double y1, double x2, double y2) {
        // 工具函数,不依赖对象状态
        return std::sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
    }
    // 工厂方法模式
    static Utility* createUtility() {
        return new Utility();
    }
};
int Utility::instanceCount = 0;
// 使用静态函数
int main() {
    std::cout << Utility::getInstanceCount(); // 直接通过类名调用
    std::cout << Utility::calculateDistance(0, 0, 3, 4); // 输出: 5
    Utility u1;
    std::cout << u1.getInstanceCount(); // 也可以通过对象调用(不推荐)
}

文件作用域的静态函数(C风格)

// 在 .cpp 文件中
static void internalHelper() {  // 只在当前文件可见
    std::cout << "内部帮助函数" << std::endl;
}
// 替代方案:使用匿名命名空间(推荐)
namespace {
    void anotherHelper() {      // 同样具有内部链接
        std::cout << "另一个帮助函数" << std::endl;
    }
}

4. 综合应用示例

单例模式(Singleton)

class DatabaseConnection {
private:
    static DatabaseConnection* instance;  // 静态实例指针
    const std::string connectionString;   // const 成员
    mutable std::mutex mtx;               // mutable:可在const函数中修改
    // 私有构造函数
    DatabaseConnection(const std::string& connStr) 
        : connectionString(connStr) {}
public:
    // 删除拷贝构造和赋值
    DatabaseConnection(const DatabaseConnection&) = delete;
    DatabaseConnection& operator=(const DatabaseConnection&) = delete;
    // 静态函数获取单例
    static DatabaseConnection* getInstance() {
        if (instance == nullptr) {
            instance = new DatabaseConnection("localhost:3306");
        }
        return instance;
    }
    // const 成员函数
    const std::string& getConnectionString() const {
        return connectionString;
    }
    // 可修改 mutable 成员的 const 函数
    void query(const std::string& sql) const {
        std::lock_guard<std::mutex> lock(mtx); // 修改 mutable 成员
        std::cout << "Executing: " << sql << std::endl;
    }
    static void cleanup() {
        delete instance;
        instance = nullptr;
    }
};
// 静态成员定义
DatabaseConnection* DatabaseConnection::instance = nullptr;

使用示例

int main() {
    // 单例使用
    DatabaseConnection* db = DatabaseConnection::getInstance();
    db->query("SELECT * FROM users");
    // const 对象使用
    const DatabaseConnection* constDb = DatabaseConnection::getInstance();
    std::cout << constDb->getConnectionString() << std::endl;
    constDb->query("SELECT * FROM products"); // 可以调用 const 函数
    DatabaseConnection::cleanup();
    return 0;
}

5. 关键要点总结

const 规则

static 规则

最佳实践

  1. 将不修改对象状态的成员函数声明为 const
  2. 使用 static 实现工具函数和单例模式
  3. 优先使用匿名命名空间替代文件作用域的 static 函数
  4. 合理使用 mutable 处理 const 函数中的特殊情况

到此这篇关于C++ const 与 static变量、函数、类成员的全面解析(最新推荐)的文章就介绍到这了,更多相关C++ const 与 static 类成员内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文