詳解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 修飾符內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: