C++中的常成員函數以及const用於函數重載

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的常成員函數和普通成員函數也是可以發生重載的

發佈了32 篇原創文章 · 獲贊 14 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章