C++中const修饰符的详解及其作用介绍

目录
  • 概述
  • 常对象
  • 常对象成员
    • 常成员函数
    • 常数据成员
    • 数据成员访问限制
    • 常对象修改的限制
  • 常指针
    • 指向常变量的指针
    • 指向对象的指针
    • 小结
  • 对象的常引用
  • 总结

概述

const 是 constant 的缩写, 是不变的意思. 在 C++ 中是用来修饰内置类型变量, 自定义对象, 成员函数, 返回值, 函数参数. const 可以帮我们避免无意之中的错误操作.

使用 const, 把有关的数据定义为常量 (常变量 / 常对象 / 常函数). const 既可以使数据在一定范围内共享, 又要保证它不被任意修改.

const 包括:

  • 常对象
  • 常指针
  • 常引用

常对象

我们可以将需要保证数据成员不改变的对象, 可以声明为常对象. 常对象中的所有成员的值都不能被修改.

常变量的两种格式:

类名 const 对象名[(实参表列)];
const 类名 对象名[(实参表列)];

常对象必须要有初始值. 例如:

Time const t1(12, 34, 46);
const Time t1(12, 34, 46);

试图改变常对象的成员值会发生什么:

int main() {

    const Time t1(10, 10, 10);  // 定义const Time对象
    t1.set_time(2,2,2);  // 试图改变t1对象的成员数据, 报错

    return 0;
}

输出:
C:\Users\Windows\CLionProjects\Project1\main.cpp: In function 'int main()':
C:\Users\Windows\CLionProjects\Project1\main.cpp:10:22: error: passing 'const Time' as 'this' argument discards qualifiers [-fpermissive]
     t1.set_time(2,2,2);
                      ^
In file included from C:\Users\Windows\CLionProjects\Project1\main.cpp:2:
C:\Users\Windows\CLionProjects\Project1\Time.h:12:10: note:   in call to 'void Time::set_time(int, int, int)'
     void set_time(int h, int m=0, int s=0);
          ^~~~~~~~
mingw32-make.exe[3]: *** [CMakeFiles\Project1.dir\build.make:81: CMakeFiles/Project1.dir/main.cpp.obj] Error 1
mingw32-make.exe[2]: *** [CMakeFiles\Makefile2:94: CMakeFiles/Project1.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:101: CMakeFiles/Project1.dir/rule] Error 2
mingw32-make.exe: *** [Makefile:136: Project1] Error 2

常对象成员

常成员函数

如果我们要引用常对象中的数据成员, 就需要将该成员函数声明为 const 型函数, 即常成员函数. 常成员函数可以访问对象中的数据成员, 但不允许修改常对象中数据成员的值.

举个栗子:

Time 类:

#ifndef PROJECT1_TIME_H
#define PROJECT1_TIME_H

class Time {
private:
    int minute;
    int second;
public:
    int hour;
    Time();  // 默认构造函数
    Time(int h, int m=0, int s=0);  // 有参构造函数
    void set_time(int h, int m=0, int s=0);
    void show_time() const;  // 声明为常成员函数
};

#endif //PROJECT1_TIME_H

Time.cpp:

#include "Time.h"
#include <iostream>
using namespace std;

// 默认构造函数
Time::Time() : hour(0), minute(0), second(0) {}

// 有参构造函数
Time::Time(int h, int m, int s) : hour(h), minute(m), second(s) {}

void Time::set_time(int h, int m, int s) {
    hour = h;
    minute = m;
    second = s;
}

void Time::show_time() const {
    cout << hour << ":" << minute << ":" << second << endl;
}

main:

#include "Time.h"
#include <iostream>
using namespace std;

int main() {

    const Time t1(10, 10, 10);  // 定义const Time对象
    t1.show_time();  // 调用常成员函数

    return 0;
}

调试输出:

10:10:10

注: const 是函数类型的一部分, 在声明函数和定义函数时都要有 const 关键字.

常数据成员

当我们用关键字 const 来声明常量数据成员, 可以限定其值不能改变.

Time 类:

#ifndef PROJECT1_TIME_H
#define PROJECT1_TIME_H

class Time {
private:

public:
    const int hour;  // 定义hour为常数据成员
    int minute;
    int second;

    Time();  // 默认构造函数
    Time(int h, int m=0, int s=0);  // 有参构造函数
    void set_time(int m=0, int s=0);
    void show_time() const;  // 声明为常成员函数
};

#endif //PROJECT1_TIME_H

因为 hour 为常数据成员, 所以我们只能通过构造函数的参数初始化表对常数据成员进行初始化.

// 默认构造函数
Time::Time() : hour(0), minute(0), second(0) {}

// 有参构造函数
Time::Time(int h, int m, int s) : hour(h), minute(m), second(s) {}

我们不能再构造函数中用赋值的方法对常数据成员初始化. 例如:

Time::Time(int h){hour=h;}  // 非法

不能用成员函数改变常数据成员的值. 例如:

void Time::setHour(int h){hour=h;}  // 非法

数据成员访问限制

常对象中的成员函数未加 const, 编译系统认为其是非 const 成员函数.

常对象修改的限制

如果一个对象被声明为常对象, 则不能调用该对象的非 const 型的成员函数, 除了由系统自动调用的隐式的构造函数和析构函数.

要点:

  • 编辑系统只检查函数的声明, 只要发现调用了常对象的成员函数, 而该函数未被声明为 const, 就报错
  • 防止函数修改常对象中数据成员的值
  • 编译系统对不安全的因素予以拦截, 为我们开发人员省了不少心
  • 用常成员函数引用常变量

常指针

将指针变量声明为 const 型, 指针值始终保持为其初始值, 不能改变.

指向对象的常指针格式:

类名 *const 变量名;
Time time1(10, 12, 15), t2;
Time * const pt = &t1  // pt 是常指针
pt = &t2; // 将一个指针固定

常见用途: 将一个指针固定地与一个对象联系. 将常指针作为函数的形参, 目的是不允许在函数执行过程中改变指针变量的值.

void doSomething(Test * const p1){
    p1 -> setX(5);
    p1 -> printxy();
}

指向常变量的指针

定义指向常变量的指针变量的一般形式为:

const 类名 *变量名 / 类型名 const *变量名;

只有常变量的指针能指向常变量:

指向常变量的指针变量可以指向未被声明为 const 的变量, 但不能通过此指针变量改变该变量的值.

重点:

  • 如果一个变量已被声明为常变量 / 对象. 我们就只能用指向常变量的指针指向他, 而不能用非 const 型的变量 / 对象的指针去指向它.

指向对象的指针

定义指向对象的指针变量的一般形式为.

const 类名 *变量名 / 类名 const *变量名;

举个栗子:

如果一个对象已经被声明为常对象, 我们就只能用指向常对象的指针指向他. 而不能用指向非 const 型变量 / 对象的指针指向他.

指向常对象的指针变量可以指向未被声明为 const 的对象, 但不能通过此指针来改变该对象的值. 例如:

小结

指向常对象的指针最常用语函数的形参, 以保护形参指针所指向的对象在函数执行过程中不被修改.

当我们希望在调用函数时对象的值不被修改, 就应当把形参定义为指向常对象的指针变量. 同时用对象的地址作为实参 (对象可以是 const 或非 const 型).

对象的常引用

一个变量的应用就是变量的别名. 变量名和引用名都指向同一段没存单元.

函数的形参可以是对象的引用. 如果不希望在函数中修改实参的值, 可以将形参声明为常引用. 例如:

void fun(Time &t);
void fun(const Time &);  // 常引用

我们应该尽量使用常引用作为函数参数, 原因有二:

  1. 既能保证数据安全, 使数据不能被随意修改
  2. 在调用函数时不必建立实参的copy, 可以提高程序运行效率

总结

到此这篇关于C++中const修饰符的详解及其作用介绍的文章就介绍到这了,更多相关C++ const内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++语言const 关键字使用方法图文详解

    之前一直在学习C/C++,关于const的使用,这里出现一点,那里出现一点.知识用时方恨少,这一段时间正好各种笔试题,其中关于const的用法也是层出不穷,所以疲于在书本上各种翻,这里汇总一下,加深自己的印象的同时,也方便以后查阅和学习.菜鸟一个,若有错误,望指正! const关键字 常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的.不管出现在任何上下文都是为这个目的而服务的. const使用方法 定义const对象 const修饰符可以把对象转变成常数对象,意

  • c++中的const_cast用法大全

    const_cast是一种C++运算符,主要是用来去除复合类型中const和volatile属性(没有真正去除). const_cast:作用: 指针或引用的转换符,用来移除变量的const或volatile限定符. 先来看c中不严谨的地方: const int ca = 30;  int* q = &ca;//C中是可以编译的,最多会得到一个warning,随后就可以对ca里的数据进行操作了. 疑问:那const几乎是失效的. 在c++编译中就会报错: error: invalid conve

  • C++ const关键字分析详解

    目录 C语言中修饰变量 C语言中修饰指针变量 C语言中修饰函数的参数 C语言中修饰函数的返回值 C++中修饰变量 C++中修饰函数的参数 C++中修饰函数的返回值 C++中修饰类的成员函数 C++中修饰类的成员变量 总结 C语言中修饰变量 在C语言中,被const修饰的是一个不能被修改的变量. C语言中修饰指针变量 #include <stdio.h> //代码1 void test1() { int n = 10; int m = 20; int *p = &n; *p = 20;/

  • C++ const限定符以及顶层const和底层const的案例详解

    目录 一.const限定符的作用 二.const和引用 三.const和指针 四.顶层const和底层const 1.顶层const 2.底层const 一.const限定符的作用 当我们在写程序的时候,想定义一种变量,它的值不会被改变,这时就可以用const限定符来定义变量,也可称它为常量,常量的定义必须要有初始值,否则编译错误.其实际例子是用一个变量来表示缓冲区的大小的时候. 对内置类型用const是比较通俗易懂的,其作用就是不能对用const定义了的变量进行修改(写),但可以进行拷贝(读)

  • 使用c++11 constexpr时遇到的坑详解

    最近在使用constexpr的时候无意中踩了个小坑. 下面给个小示例: #include <iostream> constexpr int n = 10; constexpr char *msg = "Hello, world!"; int main() { for (auto i = 0; i < n; ++i) { std::cout << msg << std::endl; } } constexpr应该是大家很熟悉的东西了,也是最常用的

  • C++中const修饰符的详解及其作用介绍

    目录 概述 常对象 常对象成员 常成员函数 常数据成员 数据成员访问限制 常对象修改的限制 常指针 指向常变量的指针 指向对象的指针 小结 对象的常引用 总结 概述 const 是 constant 的缩写, 是不变的意思. 在 C++ 中是用来修饰内置类型变量, 自定义对象, 成员函数, 返回值, 函数参数. const 可以帮我们避免无意之中的错误操作. 使用 const, 把有关的数据定义为常量 (常变量 / 常对象 / 常函数). const 既可以使数据在一定范围内共享, 又要保证它不

  • C++中static修饰符的详解及其作用介绍

    目录 概述 静态数据成员 引用静态数据成员 用类名访问数据成员 静态成员函数 综合案例 概述 static (静态) 修饰符是用来控制变量的存储方式和可见性的. 静态局部变量存储在静态区域: static 的性质: 局部特性:作用范围仅限于本函数 静态特性:存储在静态区, 函数调用结束后不孝顺而保留原值. 在下一次调用时, 保留上一次调用结束时的值. 静态数据成员 在我们定义全局变量的时候, 我们会发现一个问题: 我们可以在程序各处自由的修改全局变量的值 (不安全). 静态数据成员的特点: 静态

  • C++中浅拷贝与深拷贝的详解及其作用介绍

    目录 概述 对象的赋值 对象的复制 对象复制的用途 建立一个新对象 函数的参数为类对象 函数的返回值为类对象 浅拷贝 深拷贝 概述 浅拷贝 (shallow copy) 只是对指针的拷贝, 拷贝够两个指针指向同一个内存空间. 深拷贝 (deep copy) 不但对指针进行拷贝, 而且对指针指向的内容进行拷贝. 经过深拷贝后的指针是指向两个不同地址的指针. 对象的赋值 同类对象之间可以相互赋值. 对象赋值的一般形式: 对象名1 = 对象名2; 举个栗子: int main() { Time t1(

  • C/C++中栈(stack)&堆(heap)详解及其作用介绍

    目录 概述 程序运行中的栈和堆 堆和栈的差异 申请方式和回收方式 申请后系统的响应 申请效率比较 申请大小的限制 堆和栈中的存储内容 概述 栈 (stack) 是为执行线程流出的内存空间. 堆 (head) 是为动态分配预留的空间. 程序运行中的栈和堆 我们以一段代码来举例: #include <iostream> using namespace std; int a = 0; // 全局初始化区 char *pt; // 全局未初始化 int main() { int b; // b在栈区

  • C/C++中文件的随机读写详解及其作用介绍

    目录 概述 随机读写 函数 例子 指针流成员函数 随机访问二进制数据 概述 文件的操作方式分为顺序读写和随机读写. 顺序读写指文件的指针只能从头移到尾巴. 随机读写指文件指针可以随意移动, 根据需要. 随机读写 文件指针: 在磁盘文件操作中有一个文件指针, 用来指明进行读写的位置. 函数 文件流提供了一些有关文件指针的成员函数: 成员函数 作用 gcount() 返回最后一次输入所读入的字节数 tellg() 返回输入文件指针的当前位置 seekg (文件中的位置) 将输入文件中指针移到指定的位

  • C/C++中派生类访问属性详解及其作用介绍

    目录 保护继承 派生类成员的访问属性 总结 保护继承 由 protected 声明的成员称为 "受保护的成员", 或简称 "保护成员". 从用户的角度来看, 保护成员等价于私有成员. 保护成员可以被派生类的成员函数引用. 派生类成员的访问属性 4 种访问属性: 公用的: 类内和类外都可以访问 受保护的: 类内可以访问, 类外不能访问, 下一层的派生类可以访问 私有的: 类内可以访问, 类外不能访问 不可访问的: 类内和类外都不能访问 继承方式 基类中的成员 访问属性

  • C++中对象与类的详解及其作用介绍

    目录 什么是对象 面向过程 vs 面向对象 面向过程 面向对象 什么是类 类的格式 类的成员函数 函数访问权限 方法一 方法二 方法三 inline 成员函数 什么是对象 任何事物都是一个对象, 也就是传说中的万物皆为对象. 对象的组成: 数据: 描述对象的属性 函数: 描述对象的行为, 根据外界的信息进行相应操作的代码 具有相同的属性和行为的对象抽象为类 (class) 类是对象的抽象 对象则是类的特例 面向过程 vs 面向对象 面向过程 面向过程的设计: 围绕功能, 用一个函数实现一个功能

  • C++中构造函数与析构函数的详解及其作用介绍

    目录 构造函数 默认构造函数 有参构造函数 析构函数 析构函数例子 析构函数执行时机 局部对象 全局对象 构造函数 构造函数 (constructor) 是一种特殊的成员函数. 它会在每次创建类的新对象时执行. 构造函数的名称与类的名称是完全相同的, 并且不会返回任何类型. 构造函数可用于为某些成员变量设置初始值. 格式: Class::Class(); // 构造函数 默认构造函数 如果用户自己没有定义构造函数, C++ 系统会自动生成一个默认构造函数. 这个构造函数体是空的, 没有参数, 不

  • vue 之 .sync 修饰符示例详解

    在一些情况下,我们可能会需要对一个 prop (父子组件传递数据的属性) 进行"双向绑定". 在vue 1.x 中的 .sync 修饰符所提供的功能.当一个子组件改变了一个带 .sync 的prop的值时,这个变化也会同步到父组件中所绑定的值. 这很方便,但也会导致问题,因为它破坏了单向数据流.(数据自上而下流,事件自下而上走) 由于子组件改变 prop 的代码和普通的状体改动代码毫无区别,所以当你光看子组件的代码时,你完全不知道它合适悄悄地改变了父组件的状态. 这在 debug 复杂

  • Java四种权限修饰符知识点详解

    Java中有四种权限修饰符 public protected (default) private 同一个类 yes yes yes yes 同一个包 yes yes yes no 不同包子类 yes yes no no 不同包非子类 yes no no no Warning:(default)并不是关键字"default",而是根本不写 知识点补充: Java语言4种访问权限修饰符 Java语言4种访问权限修饰符,但是仅有3个关键字,因为不写访问权限,在Java中被称为默认权限,或同包

随机推荐