Appearance
C++ 常量
常量是其值在程序执行期间不能被修改的变量。在 C++ 中,可以使用多种方式定义常量。
1. 使用 const 关键字
const关键字是定义常量的最常用方式。
1.1 基本用法
cpp
#include <iostream>
int main() {
const int MAX_SIZE = 100;
const double PI = 3.14159;
const char NEWLINE = '\n';
std::cout << "MAX_SIZE: " << MAX_SIZE << std::endl;
std::cout << "PI: " << PI << std::endl;
// MAX_SIZE = 200; // 错误:不能修改常量
return 0;
}1.2 const 指针
const与指针结合使用时,需要注意const的位置:
cpp
#include <iostream>
int main() {
int a = 10;
int b = 20;
// 指向常量的指针
const int* ptr1 = &a;
// *ptr1 = 20; // 错误:不能通过指针修改值
ptr1 = &b; // 可以修改指针指向
// 常量指针
int* const ptr2 = &a;
*ptr2 = 20; // 可以通过指针修改值
// ptr2 = &b; // 错误:不能修改指针指向
// 指向常量的常量指针
const int* const ptr3 = &a;
// *ptr3 = 20; // 错误:不能通过指针修改值
// ptr3 = &b; // 错误:不能修改指针指向
return 0;
}1.3 const 引用
const引用可以绑定到任何表达式,但不能通过引用修改值:
cpp
#include <iostream>
int main() {
int a = 10;
const int& ref = a;
std::cout << "a = " << a << std::endl;
// ref = 20; // 错误:不能通过 const 引用修改值
a = 20; // 可以直接修改
std::cout << "a = " << a << std::endl;
return 0;
}1.4 const 成员函数
在类中,const成员函数不能修改成员变量:
cpp
#include <iostream>
#include <string>
class Student {
private:
std::string name;
int age;
public:
Student(std::string n, int a) : name(n), age(a) {}
// const 成员函数
void print() const {
std::cout << "姓名: " << name << ", 年龄: " << age << std::endl;
// age = 20; // 错误:不能修改成员变量
}
// 非 const 成员函数
void set_age(int a) {
age = a; // 可以修改成员变量
}
};
int main() {
const Student student("张三", 20);
student.print();
// student.set_age(21); // 错误:不能调用非 const 成员函数
return 0;
}2. 使用 constexpr 关键字(C++11)
constexpr关键字用于定义常量表达式,在编译时计算值。
2.1 基本用法
cpp
#include <iostream>
constexpr int MAX_SIZE = 100;
constexpr double PI = 3.14159;
constexpr int square(int x) {
return x * x;
}
int main() {
constexpr int result = square(5);
std::cout << "5 的平方: " << result << std::endl;
int arr[MAX_SIZE]; // 使用 constexpr 常量定义数组大小
return 0;
}2.2 constexpr 与 const 的区别
const:运行时常量,值可以在运行时确定constexpr:编译时常量,值必须在编译时确定
cpp
#include <iostream>
int main() {
const int a = 10; // 编译时常量
int b = 20;
const int c = b; // 运行时常量
constexpr int d = 10; // 编译时常量
// constexpr int e = b; // 错误:b 不是常量表达式
return 0;
}3. 使用 #define 预处理指令
#define预处理指令可以定义符号常量,但这种方式不推荐使用。
3.1 基本用法
cpp
#include <iostream>
#define MAX_SIZE 100
#define PI 3.14159
int main() {
std::cout << "MAX_SIZE: " << MAX_SIZE << std::endl;
std::cout << "PI: " << PI << std::endl;
return 0;
}3.2 #define 的缺点
- 没有类型检查
- 不遵循作用域规则
- 可能导致意外的宏替换
cpp
#include <iostream>
#define SQUARE(x) x * x
int main() {
int result = SQUARE(2 + 3); // 展开为 2 + 3 * 2 + 3 = 11,而不是 25
std::cout << "结果: " << result << std::endl; // 输出: 11
return 0;
}4. 使用枚举
枚举类型可以定义一组命名的常量。
4.1 基本用法
cpp
#include <iostream>
enum Color {
RED,
GREEN,
BLUE
};
int main() {
Color color = RED;
std::cout << "RED: " << RED << std::endl;
std::cout << "GREEN: " << GREEN << std::endl;
std::cout << "BLUE: " << BLUE << std::endl;
return 0;
}4.2 枚举类(C++11)
枚举类提供了更强的类型安全性:
cpp
#include <iostream>
enum class Color {
RED,
GREEN,
BLUE
};
int main() {
Color color = Color::RED;
// std::cout << color << std::endl; // 错误:不能直接输出枚举类
std::cout << static_cast<int>(color) << std::endl; // 输出: 0
return 0;
}5. 常量的命名规范
常量通常使用大写字母,单词之间用下划线分隔:
cpp
const int MAX_SIZE = 100;
const double PI = 3.14159;
const std::string DEFAULT_NAME = "Unknown";6. 常量的作用域
常量的作用域与变量相同,可以是局部常量或全局常量。
6.1 局部常量
cpp
#include <iostream>
int main() {
const int LOCAL_CONST = 10;
std::cout << LOCAL_CONST << std::endl;
return 0;
}6.2 全局常量
cpp
#include <iostream>
const int GLOBAL_CONST = 100;
int main() {
std::cout << GLOBAL_CONST << std::endl;
return 0;
}7. 常量表达式
常量表达式是在编译时可以计算其值的表达式。
7.1 常量表达式示例
cpp
#include <iostream>
constexpr int MAX_SIZE = 100;
constexpr int ARRAY_SIZE = MAX_SIZE * 2;
int main() {
int arr[ARRAY_SIZE]; // 使用常量表达式定义数组大小
std::cout << "数组大小: " << ARRAY_SIZE << std::endl;
return 0;
}8. const 与指针的详细说明
8.1 三种 const 指针形式
cpp
#include <iostream>
int main() {
int a = 10;
int b = 20;
// 1. 指向常量的指针:不能通过指针修改值,但可以修改指针指向
const int* ptr1 = &a;
std::cout << "*ptr1 = " << *ptr1 << std::endl;
// *ptr1 = 20; // 错误
ptr1 = &b; // 正确
// 2. 常量指针:不能修改指针指向,但可以通过指针修改值
int* const ptr2 = &a;
std::cout << "*ptr2 = " << *ptr2 << std::endl;
*ptr2 = 20; // 正确
// ptr2 = &b; // 错误
// 3. 指向常量的常量指针:既不能修改指针指向,也不能通过指针修改值
const int* const ptr3 = &a;
std::cout << "*ptr3 = " << *ptr3 << std::endl;
// *ptr3 = 20; // 错误
// ptr3 = &b; // 错误
return 0;
}9. 示例:综合运用
现在,让我们看一个综合运用各种常量的例子:
cpp
#include <iostream>
#include <string>
#include <cmath>
// 全局常量
const int MAX_STUDENTS = 50;
constexpr double PI = 3.14159;
// 枚举
enum class Grade {
A,
B,
C,
D,
F
};
// 类
class Circle {
private:
double radius;
public:
Circle(double r) : radius(r) {}
// const 成员函数
double area() const {
return PI * radius * radius;
}
double circumference() const {
return 2 * PI * radius;
}
void set_radius(double r) {
radius = r;
}
};
// constexpr 函数
constexpr int factorial(int n) {
return (n <= 1) ? 1 : n * factorial(n - 1);
}
int main() {
// const 变量
const int age = 20;
const double height = 1.75;
const std::string name = "张三";
// constexpr 变量
constexpr int result = factorial(5);
// 枚举
Grade grade = Grade::A;
// 类对象
const Circle circle(5.0);
std::cout << "圆的面积: " << circle.area() << std::endl;
std::cout << "圆的周长: " << circle.circumference() << std::endl;
// const 指针
int a = 10;
const int* ptr = &a;
std::cout << "*ptr = " << *ptr << std::endl;
// 输出常量
std::cout << "\n常量值:" << std::endl;
std::cout << "MAX_STUDENTS: " << MAX_STUDENTS << std::endl;
std::cout << "PI: " << PI << std::endl;
std::cout << "age: " << age << std::endl;
std::cout << "height: " << height << std::endl;
std::cout << "name: " << name << std::endl;
std::cout << "grade: " << static_cast<int>(grade) << std::endl;
std::cout << "5! = " << result << std::endl;
return 0;
}小结
C++ 常量包括:
const 关键字:
- 定义常量变量
- const 指针:指向常量的指针、常量指针、指向常量的常量指针
- const 引用
- const 成员函数
constexpr 关键字(C++11):
- 定义编译时常量
- constexpr 函数
#define 预处理指令:
- 定义符号常量(不推荐使用)
枚举:
- 定义一组命名的常量
- 枚举类(C++11)
常量的命名规范:
- 使用大写字母
- 单词之间用下划线分隔
常量的作用域:
- 局部常量
- 全局常量
常量表达式:
- 在编译时可以计算其值的表达式
使用常量可以提高代码的可读性和可维护性,防止意外的修改。在后续章节中,我们将学习 C++ 的修饰符类型。