C++<第二十三篇>:常量运算符

2022-01-24  本文已影响0人  NoBugException

在类中,如果你不希望某些数据被修改,可以使用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];

[本章完...]

上一篇下一篇

猜你喜欢

热点阅读