C++知識(shí)點(diǎn)之成員函數(shù)中const的用法
const 在C++中是一個(gè)很重要的關(guān)鍵字,其不光可以用來(lái)修飾變量,還可以放在函數(shù)定義中,這里整理了其在函數(shù)中的三個(gè)用法。
修飾入?yún)?/h2>
首先我們要明白在C++中調(diào)用函數(shù)時(shí)存在兩種方法,即傳遞值和傳遞引用。
值傳遞
值傳遞時(shí),調(diào)用函數(shù)時(shí)會(huì)創(chuàng)建入?yún)⒌目截?,函?shù)中的操作不會(huì)對(duì)原值進(jìn)行修改,因此這種方式中不需要使用 const 來(lái)修飾入?yún)?,因?yàn)槠渲皇菍?duì)拷貝的臨時(shí)對(duì)象進(jìn)行操作。
址傳遞
傳遞地址時(shí)函數(shù)中的操作實(shí)際上是直接對(duì)原來(lái)的值進(jìn)行修改,因此我們這里可以使用 const 修飾入?yún)ⅰ?/p>
const修飾入?yún)?/h3>
當(dāng)const修飾函數(shù)入?yún)r(shí)表示該參數(shù)不能被修改,這個(gè)是最好理解的,比如一個(gè)函數(shù)的功能是拷貝,那么入?yún)⒅械脑次募紩?huì)用 const 修飾。
void A::show(const int *b) { cout << "show const"; // error: read-only variable is not assignable // *b = 2; cout << b << endl; }
接下來(lái)我們要關(guān)注的是這里 const 對(duì)于函數(shù)重載的作用,這里給出結(jié)論,歡迎大家討論,對(duì)應(yīng)按值傳遞的函數(shù)來(lái)說(shuō) const 不會(huì)有重載的效果,但是傳遞指針和引用是會(huì)有重載的效果。
void A::show(const int b) // void A::show(int b) // error class member cannot be redeclared void display(int *num); // overload void display(const int *num); // overload void fun(A &a); // overload void fun(const A &a); // overload
函數(shù)重載的關(guān)鍵是函數(shù)的參數(shù)列表——即函數(shù)特征標(biāo)(function signature)。如果兩個(gè)函數(shù)的參數(shù)數(shù)目和類型相同,并且參數(shù)的排列順序也相同,則他們的特征標(biāo)相同,而變量名是無(wú)關(guān)緊要的。
總結(jié)一下注意點(diǎn):
- 如果輸入?yún)?shù)采用“值傳遞”,**由于函數(shù)將自動(dòng)產(chǎn)生臨時(shí)變量用于復(fù)制該參數(shù),該輸入?yún)?shù)本來(lái)就無(wú)需保護(hù),所以不要加 const 修飾。**例如不要將函數(shù) void Func1(int x) 寫成 void Func1(const int x)。
- 如果參數(shù)作為輸出參數(shù),不論它是什么數(shù)據(jù)類型,也不論它采用“指針傳遞”還是“引用傳遞”,都不能加 const 修飾,否則該參數(shù)將失去輸出功能(因?yàn)橛?const 修飾之后,不能改變他的值)。
- 如果參數(shù)作為輸入?yún)?shù),可以防止數(shù)據(jù)被改變,起到保護(hù)作用,增加程序的健壯性,建議是能加const盡量加上
上述測(cè)試代碼如下:
#include <iostream> using namespace std; class A { private: int a; public: A(int a) { this->a = a; } void show(int b); // error redeclared // void show(const int b); void display(int *num); // ok void display(const int *num); // ok void fun(A &a); void fun(const A &a); void happy(int * h); void hour(const int * h); }; void A::show(int b) { cout << "show: " << b << endl; } void A::display(int *num) { cout << "display:" << *num << endl; } void A::display(const int *num) { cout << "const display:" << *num << endl; } void A::fun(A &obj) { cout << "fun: " << obj.a << endl; } void A::fun(const A &obj) { cout << "const fun: " << obj.a << endl; } void A::happy(int *h) { cout << "happy:" << *h << endl; } void A::hour(const int *h) { cout << "const hour:" << *h << endl; } int main() { A a(1); const A a2(11); int b1 = 2; const int b2 = 3; // test overload a.show(b1); a.show(b2); a.display(&b1); a.display(&b2); a.fun(a); a.fun(a2); // test const a.happy(&b1); // a.happy(&b2); // error cannot initialize a parameter of type 'int *' with an rvalue of type 'const int *' a.hour(&b1); a.hour(&b2); return 0; } // ouptut show: 2 show: 3 display:2 const display:3 fun: 1 const fun: 11 happy:2 const hour:2 const hour:3
修飾返回值
const 修飾返回值時(shí),表示返回值不能被修改。
需要注意的是如果函數(shù)返回值采用“值傳遞方式”,由于函數(shù)會(huì)把返回值復(fù)制到外部臨時(shí)的存儲(chǔ)單元中,加 const 修飾沒(méi)有任何價(jià)值。如果返回的是引用或指針,表示不能修改指向的數(shù)據(jù)。
一般用得多的是返回值是引用的函數(shù), 可以肯定的是這個(gè)引用必然不是臨時(shí)對(duì)象的引用, 因此一定是成員變量或者是函數(shù)參數(shù), 所以在返回的時(shí)候?yàn)榱吮苊馄涑蔀樽笾当恍薷?,就需要加上const關(guān)鍵字來(lái)修飾。
我們可以看如下代碼示例:
#include <iostream> using namespace std; class Alice { private: int a; public: Alice(int a): a(a) {} int get_a() {return a;} const int* get_const_ptr() {return &a;} int* get_ptr() {return &a;} }; int main() { Alice alice(1); int a1 = alice.get_a(); // ok cout << a1 << endl; const int a2 = alice.get_a(); // ok cout << a2 << endl; // error cannot initialize a variable of type 'int *' with an rvalue of type 'const int *' // int* b1 = alice.get_const_ptr(); const int* b2 = alice.get_const_ptr(); // ok cout << *b2 << endl; // ok // *b2 = 3; // error read-only variable is not assignable *(alice.get_ptr()) = 3; cout << alice.get_a() << endl; // 3 return 0; }
修飾函數(shù)
const 也可以用來(lái)放在函數(shù)末尾,用來(lái)修飾成員函數(shù),表明其是一個(gè)常成員函數(shù),這個(gè)對(duì)于初次接觸C++的同學(xué)來(lái)說(shuō)會(huì)有點(diǎn)陌生,不過(guò)這也是C++中嚴(yán)謹(jǐn)?shù)牡胤健?/p>
先看代碼示例,學(xué)習(xí)任何編程技術(shù)都一定要寫對(duì)應(yīng)的代碼,把它跑起來(lái)并分析結(jié)果才算是真正學(xué)會(huì)了,不會(huì)你只是知道了這個(gè)知識(shí)點(diǎn),只知其然而不知其所以然。
紙上得來(lái)終覺(jué)淺,絕知此事要躬行,這里的要躬行指的就是寫代碼。
首先來(lái)看如下的代碼
class Alice { private: int a; public: Alice(int a): a(a) {} void show(); }; void Alice::show() { cout << "hello Alice" << endl; } int main() { const Alice a(1); // error: 'this' argument to member function 'show' has type 'const Alice', but function is not marked const // a.show(); return 0; }
上述代碼會(huì)報(bào)錯(cuò),因?yàn)?show() 方法不是常成員函數(shù),而 a 是常對(duì)象。
本質(zhì)上,成員函數(shù)中都有一個(gè)隱含的入?yún)?this, 這個(gè) this指的就是調(diào)用該方法的對(duì)象,而如果在函數(shù)的后面加上 const,那么這個(gè) const 實(shí)際上修飾的就是這個(gè) this。
也就是說(shuō)函數(shù)后加上了 const,表明這個(gè)函數(shù)不會(huì)改變調(diào)用者對(duì)象。
這里借用侯捷老師的圖片
上面圖片表明,在正常情況下:
non-const
對(duì)象可以調(diào)用const 或者 non-const 成員函數(shù)const
對(duì)象 只可以調(diào)用 const 成員函數(shù)
補(bǔ)充一點(diǎn),**如果成員函數(shù)同時(shí)具有 const 和 non-const 兩個(gè)版本的話, const 對(duì)象只能調(diào)用const成員函數(shù), non-const 對(duì)象只能調(diào)用 non-const 成員函數(shù)。
**如以下代碼示例
#include <iostream> using namespace std; class R { public: R(int r1, int r2) { a = r1; b = r2; } void print(); void print() const; private: int a; int b; }; void R::print() { cout << "normal print" << endl; cout << a << ", " << b << endl; } void R::print() const { cout << "const print" << endl; cout << a << ", " << b << endl; } int main() { R a(5, 3); a.print(); const R b(6 ,6); b.print(); return 0; } // output normal print 5, 3 const print 6, 6
這里也是建議能加 const 的時(shí)候就加。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C++使用一個(gè)棧實(shí)現(xiàn)另一個(gè)棧的排序算法示例
這篇文章主要介紹了C++使用一個(gè)棧實(shí)現(xiàn)另一個(gè)棧的排序算法,結(jié)合實(shí)例形式分析了C++借助輔助棧實(shí)現(xiàn)棧排序算法的相關(guān)操作技巧,需要的朋友可以參考下2017-05-05C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之 折半查找實(shí)例詳解
這篇文章主要介紹了C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之 折半查找實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-06-06使用?Visual?Studio?2022?開(kāi)發(fā)?Linux?C++?應(yīng)用程序的過(guò)程詳解
Visual?Studio?2022?引入了用于?Linux?C++?開(kāi)發(fā)的本機(jī)?WSL2?工具集,可以構(gòu)建和調(diào)試?Linux?C++?代碼,并提供了非常好的?Linux?文件系統(tǒng)性能、GUI?支持和完整的系統(tǒng)調(diào)用兼容性,這篇文章主要介紹了使用Visual?Studio?2022?開(kāi)發(fā)?Linux?C++?應(yīng)用程序,需要的朋友可以參考下2021-11-11C語(yǔ)言內(nèi)存函數(shù)的實(shí)現(xiàn)示例
本文主要介紹了C語(yǔ)言內(nèi)存函數(shù)的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-08-08C語(yǔ)言 fseek(f,0,SEEK_SET)函數(shù)案例詳解
這篇文章主要介紹了C語(yǔ)言 fseek(f,0,SEEK_SET)函數(shù)案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08詳解如何利用C++實(shí)現(xiàn)一個(gè)反射類
這篇文章主要為大家詳細(xì)介紹了如何利用C++實(shí)現(xiàn)一個(gè)反射類,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-03-03C++實(shí)現(xiàn)LeetCode(108.將有序數(shù)組轉(zhuǎn)為二叉搜索樹(shù))
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(108.將有序數(shù)組轉(zhuǎn)為二叉搜索樹(shù)),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07