詳解C++ const修飾符
概述
const 是 constant 的縮寫(xiě), 是不變的意思. 在 C++ 中是用來(lái)修飾內(nèi)置類型變量, 自定義對(duì)象, 成員函數(shù), 返回值, 函數(shù)參數(shù). const 可以幫我們避免無(wú)意之中的錯(cuò)誤操作.
使用 const, 把有關(guān)的數(shù)據(jù)定義為常量 (常變量 / 常對(duì)象 / 常函數(shù)). const 既可以使數(shù)據(jù)在一定范圍內(nèi)共享, 又要保證它不被任意修改.
const 包括:
- 常對(duì)象
- 常指針
- 常引用
常對(duì)象
我們可以將需要保證數(shù)據(jù)成員不改變的對(duì)象, 可以聲明為常對(duì)象. 常對(duì)象中的所有成員的值都不能被修改.
常變量的兩種格式:
類名 const 對(duì)象名[(實(shí)參表列)]; const 類名 對(duì)象名[(實(shí)參表列)];
常對(duì)象必須要有初始值. 例如:
Time const t1(12, 34, 46); const Time t1(12, 34, 46);
試圖改變常對(duì)象的成員值會(huì)發(fā)生什么:
int main() { const Time t1(10, 10, 10); // 定義const Time對(duì)象 t1.set_time(2,2,2); // 試圖改變t1對(duì)象的成員數(shù)據(jù), 報(bào)錯(cuò) 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
常對(duì)象成員
常成員函數(shù)
如果我們要引用常對(duì)象中的數(shù)據(jù)成員, 就需要將該成員函數(shù)聲明為 const 型函數(shù), 即常成員函數(shù). 常成員函數(shù)可以訪問(wèn)對(duì)象中的數(shù)據(jù)成員, 但不允許修改常對(duì)象中數(shù)據(jù)成員的值.
舉個(gè)栗子:
Time 類:
#ifndef PROJECT1_TIME_H #define PROJECT1_TIME_H class Time { private: int minute; int second; public: int hour; Time(); // 默認(rèn)構(gòu)造函數(shù) Time(int h, int m=0, int s=0); // 有參構(gòu)造函數(shù) void set_time(int h, int m=0, int s=0); void show_time() const; // 聲明為常成員函數(shù) }; #endif //PROJECT1_TIME_H
Time.cpp:
#include "Time.h" #include <iostream> using namespace std; // 默認(rèn)構(gòu)造函數(shù) Time::Time() : hour(0), minute(0), second(0) {} // 有參構(gòu)造函數(shù) 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對(duì)象 t1.show_time(); // 調(diào)用常成員函數(shù) return 0; }
調(diào)試輸出:
10:10:10
注: const 是函數(shù)類型的一部分, 在聲明函數(shù)和定義函數(shù)時(shí)都要有 const 關(guān)鍵字.
常數(shù)據(jù)成員
當(dāng)我們用關(guān)鍵字 const 來(lái)聲明常量數(shù)據(jù)成員, 可以限定其值不能改變.
Time 類:
#ifndef PROJECT1_TIME_H #define PROJECT1_TIME_H class Time { private: public: const int hour; // 定義hour為常數(shù)據(jù)成員 int minute; int second; Time(); // 默認(rèn)構(gòu)造函數(shù) Time(int h, int m=0, int s=0); // 有參構(gòu)造函數(shù) void set_time(int m=0, int s=0); void show_time() const; // 聲明為常成員函數(shù) }; #endif //PROJECT1_TIME_H
因?yàn)?hour 為常數(shù)據(jù)成員, 所以我們只能通過(guò)構(gòu)造函數(shù)的參數(shù)初始化表對(duì)常數(shù)據(jù)成員進(jìn)行初始化.
// 默認(rèn)構(gòu)造函數(shù) Time::Time() : hour(0), minute(0), second(0) {} // 有參構(gòu)造函數(shù) Time::Time(int h, int m, int s) : hour(h), minute(m), second(s) {}
我們不能再構(gòu)造函數(shù)中用賦值的方法對(duì)常數(shù)據(jù)成員初始化. 例如:
Time::Time(int h){hour=h;} // 非法
不能用成員函數(shù)改變常數(shù)據(jù)成員的值. 例如:
void Time::setHour(int h){hour=h;} // 非法
數(shù)據(jù)成員訪問(wèn)限制
常對(duì)象中的成員函數(shù)未加 const, 編譯系統(tǒng)認(rèn)為其是非 const 成員函數(shù).
常對(duì)象修改的限制
如果一個(gè)對(duì)象被聲明為常對(duì)象, 則不能調(diào)用該對(duì)象的非 const 型的成員函數(shù), 除了由系統(tǒng)自動(dòng)調(diào)用的隱式的構(gòu)造函數(shù)和析構(gòu)函數(shù).
要點(diǎn):
- 編輯系統(tǒng)只檢查函數(shù)的聲明, 只要發(fā)現(xiàn)調(diào)用了常對(duì)象的成員函數(shù), 而該函數(shù)未被聲明為 const, 就報(bào)錯(cuò)
- 防止函數(shù)修改常對(duì)象中數(shù)據(jù)成員的值
- 編譯系統(tǒng)對(duì)不安全的因素予以攔截, 為我們開(kāi)發(fā)人員省了不少心
- 用常成員函數(shù)引用常變量
常指針
將指針變量聲明為 const 型, 指針值始終保持為其初始值, 不能改變.
指向?qū)ο蟮某V羔樃袷?
類名 *const 變量名; Time time1(10, 12, 15), t2; Time * const pt = &t1 // pt 是常指針 pt = &t2; // 將一個(gè)指針固定
常見(jiàn)用途: 將一個(gè)指針固定地與一個(gè)對(duì)象聯(lián)系. 將常指針作為函數(shù)的形參, 目的是不允許在函數(shù)執(zhí)行過(guò)程中改變指針變量的值.
void doSomething(Test * const p1){ p1 -> setX(5); p1 -> printxy(); }
指向常變量的指針
定義指向常變量的指針變量的一般形式為:
const 類名 *變量名 / 類型名 const *變量名;
只有常變量的指針能指向常變量:
指向常變量的指針變量可以指向未被聲明為 const 的變量, 但不能通過(guò)此指針變量改變?cè)撟兞康闹?
重點(diǎn):
如果一個(gè)變量已被聲明為常變量 / 對(duì)象. 我們就只能用指向常變量的指針指向他, 而不能用非 const 型的變量 / 對(duì)象的指針去指向它.
指向?qū)ο蟮闹羔?/h3>
定義指向?qū)ο蟮闹羔樧兞康囊话阈问綖?
const 類名 *變量名 / 類名 const *變量名;
舉個(gè)栗子:
如果一個(gè)對(duì)象已經(jīng)被聲明為常對(duì)象, 我們就只能用指向常對(duì)象的指針指向他. 而不能用指向非 const 型變量 / 對(duì)象的指針指向他.
指向常對(duì)象的指針變量可以指向未被聲明為 const 的對(duì)象, 但不能通過(guò)此指針來(lái)改變?cè)搶?duì)象的值. 例如:
小結(jié)
指向常對(duì)象的指針最常用語(yǔ)函數(shù)的形參, 以保護(hù)形參指針?biāo)赶虻膶?duì)象在函數(shù)執(zhí)行過(guò)程中不被修改.
當(dāng)我們希望在調(diào)用函數(shù)時(shí)對(duì)象的值不被修改, 就應(yīng)當(dāng)把形參定義為指向常對(duì)象的指針變量. 同時(shí)用對(duì)象的地址作為實(shí)參 (對(duì)象可以是 const 或非 const 型).
對(duì)象的常引用
一個(gè)變量的應(yīng)用就是變量的別名. 變量名和引用名都指向同一段沒(méi)存單元.
函數(shù)的形參可以是對(duì)象的引用. 如果不希望在函數(shù)中修改實(shí)參的值, 可以將形參聲明為常引用. 例如:
void fun(Time &t); void fun(const Time &); // 常引用
我們應(yīng)該盡量使用常引用作為函數(shù)參數(shù), 原因有二:
- 既能保證數(shù)據(jù)安全, 使數(shù)據(jù)不能被隨意修改
- 在調(diào)用函數(shù)時(shí)不必建立實(shí)參的copy, 可以提高程序運(yùn)行效率
總結(jié)
到此這篇關(guān)于C++ const 修飾符的文章就介紹到這了,更多相關(guān)C++ const 修飾符內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
VS2010/MFC編程(常用控件:樹(shù)形控件Tree Control控件創(chuàng)建h和實(shí)例)
本篇文章介紹了VS2010/MFC編程:常用控件:樹(shù)形控件Tree Control,包括樹(shù)形控件的創(chuàng)建、CTreeCtrl類的主要成員函數(shù)和應(yīng)用實(shí)例有興趣的可以了解一下。2016-12-12C++11?成員函數(shù)作為回調(diào)函數(shù)的使用方式
這篇文章主要介紹了C++11?成員函數(shù)作為回調(diào)函數(shù)的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11C語(yǔ)言采用文本方式和二進(jìn)制方式打開(kāi)文件的區(qū)別分析
這篇文章主要介紹了C語(yǔ)言采用文本方式和二進(jìn)制方式打開(kāi)文件的區(qū)別分析,有助于讀者更好的理解文本文件與二進(jìn)制文件的原理,需要的朋友可以參考下2014-07-07C++使用Kruskal和Prim算法實(shí)現(xiàn)最小生成樹(shù)
這篇文章主要介紹了C++使用Kruskal和Prim算法實(shí)現(xiàn)最小生成樹(shù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01vscode cmake compilers配置路徑的實(shí)現(xiàn)
本文主要介紹了vscode cmake compilers配置路徑的實(shí)現(xiàn),文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-03-03在vscode中快速新建html文件的2種方法總結(jié)
這篇文章主要給大家介紹了關(guān)于在vscode中快速新建html文件的2種方法,以及如何快速打開(kāi)HTML文件查看編輯效果的方法,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04C語(yǔ)言樹(shù)與二叉樹(shù)基礎(chǔ)全刨析
二叉樹(shù)可以簡(jiǎn)單理解為對(duì)于一個(gè)節(jié)點(diǎn)來(lái)說(shuō),最多擁有一個(gè)上級(jí)節(jié)點(diǎn),同時(shí)最多具備左右兩個(gè)下級(jí)節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)。本文將詳細(xì)介紹一下C中二叉樹(shù)與樹(shù)的概念和結(jié)構(gòu),需要的可以參考一下2022-04-04C++程序的執(zhí)行順序結(jié)構(gòu)以及關(guān)系和邏輯運(yùn)算符講解
這篇文章主要介紹了C++程序的執(zhí)行順序結(jié)構(gòu)以及關(guān)系和邏輯運(yùn)算符講解,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-09-09