在类中,如果你不希望某些数据被修改,可以使用const关键字加以限定。const 可以用来修饰成员变量和成员函数。
(1)const成员变量
const成员变量又称 常成员变量,简称 常量。
常量必须在定义的时候就初始化,否则编译器会报错。
错误的写法:
const int a;
正确的写法:
const int a = 10;
除此之外,常量不可变,如果强制给他重新赋值,那么编译器会报错。
(2)const成员函数
Student.h文件
#include <iostream>
class Student
{
private:
int16_t mScore; // 成绩
public:
void setScore(int score);
int getScore() const;
};
Student.cpp文件
#include "Student.h"
void Student::setScore(int score)
{
mScore = score;
}
int Student::getScore() const
{
return mScore;
}
在 getScore 函数后面添加const关键字,这样的函数叫做 const成员函数,即 常成员函数。
编译器不允许在 常成员函数 内修改成员变量的值。
getScore 函数的功能很简单,仅仅是为了获取成员变量的值,没有任何修改成员变量的企图,所以加了 const 限制,这是一种保险的做法,同时也使得语义更加明显。
(3)常量返回值
Student.h文件
#include <iostream>
class Student
{
private:
int16_t mScore; // 成绩
public:
void setScore(int score);
const int getScore();
};
Student.cpp文件
#include "Student.h"
void Student::setScore(int score)
{
mScore = score;
}
const int Student::getScore()
{
return mScore;
}
以上代码,将 const 放在函数返回值类型的前面,这样的函数的返回值就是常量整数类型。
需要注意和 常成员函数 的区别。
(4)const对象(常对象)
在 C++ 中,const 也可以用来修饰对象,称为 常对象。一旦将对象定义为常对象之后,就只能调用类的 const 成员(包括 const 成员变量和 const 成员函数)了。
const Student student;
student对象是 常对象,此时student只能调用 常量 和 常成员函数 了。
(5)常量指针与指针常量
常量指针:如果在定义指针变量的时候,指针变量前用const修饰,被定义的指针变量就是指向常量的指针变量,指向常量的指针变量称为常量指针,格式如下
const int* p = &a; // * p 是常量
int const* p = &a; // * p 是常量
以上两种写法是一致的。常量指针本质上是一个指针。
指针常量:顾名思义它就是一个常量,但是是指针修饰的,格式如下
int* const p = &a; // p 是常量
指针常量本质上是一个常量,所以p必须在定义的时候初始化。
两者可以结合使用,即指向常量的指针常量:
const int* const p = &a;
(6)常量引用
先看下非常量引用的代码:
int a = 10;
int& ref = a;
引用 ref 指向变量 a;
常量引用既可以指向非常量,也可以指向常量:
int a = 10;
const int& ref = a; // 指向非常量
---------------------------------------
const int a = 10;
const int& ref = a; // 指向常量
常量引用不可以重新指向变量。
但是,非常量引用不可以指向常量,如下代码是错误的:
const int a = 10;
int& ref = a;
(7)当临时变量遇到非常量引用
int a = 3, b = 4;
int& ref1 = a;
int& ref2 = b;
以上代码是应用的常规写法,是没问题的。但是如果是这样呢?
int a = 3, b = 4;
int& ref = a + b;
a+b 之后是一个临时变量,如果直接使用 ref 引用指向这个临时变量是错误的,编译器会报错。
临时变量 如果一定是被引用指向的话,那必须是被一个常量引用指向,即:
const int& ref = a + b;
举一个例子:
void function(const int& ref)
{
cout << ref << endl;
}
int main()
{
int a = 3, b = 4;
function(a + b);
cout << a << endl;
return 0;
}
函数 function 的形式参数之所以写成常量,是因为传入的实参为 a + b,即临时变量,由于C++语法的限制,这种情况应该将 函数 function 参数加上 const 关键字。
常量不可以成为左值,如下代码是错误的,编译器不会承认:
void function(const int& ref)
{
ref = 3;
}
总之,一个函数的形式参数是否添加const,取决于形参的行为,常量不能称为左值,左值是一个变量,而不是常量。
(7)函数后面添加const
非静态成员函数后面加const,类似如下函数:
class Base {
public:
void setA(int a) const
{
this->mA = a;
}
private:
int mA;
};
表示成员函数隐含传入的this指针为 const指针,
决定了在该成员函数中,任意修改它所在的类的成员的操作都是不允许的,因为隐含了对this指针的const引用。
就是说不会改变对象中成员变量的数值。
以上函数中 this->mA = a 是不被允许的。
(8)C 和 C++ 有关常量的一个区别
先看下代码:
const int a = 10;
int* p = &a;
*p = 2;
cout << a << endl;
cout << *p << endl;
以上代码在 C 中是没问题的,打印结果是:
2
2
但在C++下会提示, const int* 类型的值不能用于初始化 int* 类型的实体
以及 无法从 const int* 转成 int*
错误,这里需要做一下强制转换:
int* p = (int*) & a;
C++的输出结果是:
10
2
在 C 中编译器会为常量分配内存;
在 C++ 中对于基本类型的常量,编译器并不为其分配存储空间,编译器会把它放到 符号表,当取符号常量的地址等操作时,将强迫编译器为这些常量分配存储空间,编译器会重新在内存中创建一个它的拷贝, 通过地址访问到的就是这个拷贝,而非原始的符号常量;
除此之外,C 的常量不能用来确定数组的大小,但是 C++ 的常量是可以用来确定数组的大小的,如下:
const int size = 10;
int name[size];
[本章完...]
网友评论