1.什麼是常成員函數?
在類中可以含有普通成員函數和靜態成員函數,而使用 const修飾的普通成員函數稱爲 常成員函數
const修飾的是普通成員函數中的this指針指向的內存空間
類的普通成員函數中都存在隱藏的 this指針,比如:
class Test
{
private:
int a;
int b;
public:
Test(int a,int b)
{
this->a = a;
this->b = b;
}
void printT()
{
cout << "a = " << this->a << ",b = " << this->b << endl;
}
}
//在C++編譯器底層,void printT()函數是這樣實現的
void printT(Test *const this) //是一個const型的指針,一旦實參傳過來後,指針本身指向就不可以被修改
{
cout << "a = " << this->a << ",b = " << this->b << endl;
//類中的成員變量相當於結構體中的屬性,用類定義對象T,相當於用
//結構體類型定義變量T, 然後對象T調用方法時 相當於結構體變量T調用方法,T此時是一個棧空間變量
//調用printT()函數方法時,T會將自己的變量內存空間首地址傳給函數printT(),所以對象TT調用方法時相當於把自身的地址也傳入了函數中作爲一個參數,但C++編譯器給我們隱藏了而已
}
這是C++底層綁定成員的方法,而常成員函數是指在此基礎上再加一個 const 進行修飾,修飾 this指針指向的內存空間
void printT() const
{
cout << "a = " << this->a << ",b = " << this->b << endl;
}
此時const修飾的是this指針所指向的內存空間,即指向的內存空間的量不可改變,映射到底層表現爲
void printT(const Test *const this)
{
cout << "a = " << this->a << ",b = " << this->b << endl;
}
綠色const是普通成員函數和常成員函數均有的,表示的是 指針本身的指向一旦確定不可修改,即 指針常量
而紅色const是在普通成員函數括號後面編程 自己添加的,表示的是 指針指向的內存空間的值不可被修改,是一個常量指針,從而this指針是一個指向常量的常量指針
此時該成員函數稱爲 常成員函數
2.常成員函數的特點:
由於常成員函數中 this指針指向常量,所以常成員函數不能夠完成修改 類屬性的值的操作,比如:
class Change:
{
private:
int a;
public:
void changeA(int A) // #1
{
this.a = A;
}
void changeA(int A) const // #2
{
this.a = A;
}
}
在上方中,#2 的操作是錯誤的
同時還要注意:
3.
常成員函數 不能調用 普通成員函數(因爲普通成員函數中可能出現更新成員屬性值的操作),可以調用其他常成員函數
而普通成員函數是可以調用常成員函數的
4.const關鍵字來進行函數的重載,還是在上方change類中:
int getval(int val)
{
return val+3;
}
int getval(int val) const
{
return val - 3;
}
而兩者互爲重載
規則是 常對象(實例化時必須用const進行修飾)調用 常成員函數, 普通對象調用 普通成員函數
5.其他關於const位置的小結
還是對於函數,const來修飾函數的返回值
const來修飾函數的返回值時 分爲 指針返回,值返回
5.1當函數是指針返回時,該返回值只能返回給 用 const修飾的同類型的指針
const int* getval()
{
int* tmp = new int(10);
return tmp;
}
由於函數返回指針所指向的值不能被修改,所以
int* a = getval(); //編譯錯誤
const int* b = getval(); //正確
5.2當函數是值返回時,由於返回的值要賦值給另外一個內存空間,所以此時加不加const影響不大
6.const 修飾成員變量
int const a;
const int a;
兩者等價,定義常量a
const int* a;
int const* a;
兩者等價,均爲定義了 常量指針,即指針指向的值不可改變
int * const a;
定義了一個 指針常量,即 指針的指向不可改變
7.const修飾函數參數
const修飾函數參數時,就帶來了一個問題。是否可以 根據 函數參數中的 const來進行函數重載,答案是可以的
主要看的就是 函數中的 參數是否 等價於一樣,如果等價於一樣,則編譯器提示錯誤,函數重定義
如果兩者不等價,則根據參數類型發生函數重載
比如:
#include<iostream>
using namespace std;
void fun(const int i)
{
cout << "fun(const int) called ";
}
void fun(int i)
{
cout << "fun(int ) called " ;
}
int main()
{
const int i = 10;
fun(i);
return 0;
}
這樣編譯則會出錯,提示重定義,而不是發生重載
原因在於 函數調用中存在實參和形參的結合,我們的實參 i=10; 不管有沒有 const,都不會改變實參的值
再如:
#include<iostream>
using namespace std;
void fun(char *a)
{
cout << "non-const fun() " << a;
}
void fun(const char *a)
{
cout << "const fun() " << a;
}
int main()
{
const char *ptr = "hello world";
fun(ptr);
return 0;
}
其中, char* a 指向的是 字符串變量, const char * a指向的是 字符串常量,兩者對於實參是不一樣的,前者可以改變實參指向的值,而後者無法改變
但是對於下面的:
#include<iostream>
using namespace std;
void fun(char *a)
{
cout << "non-const fun() " << a;
}
void fun(char * const a)
{
cout << "const fun() " << a;
}
int main()
{
char ptr[] = "hello world";
fun(ptr);
return 0;
}
char* a 與 char* const a 前者是 指針變量,後者是指針常量, 但是由於 函數參數的 實參與形參結合, 兩者對於實參來講是一樣的,並不會改變實參的值
所以,綜上,函數參數中的 const是可以看做函數重載的標誌,但是要視具體情況而言
此外,上面已經知道 帶const的常成員函數和普通成員函數也是可以發生重載的