C++之const類成員變量,const成員函數

const修飾類的成員函數

const修飾變量通常有兩種方式:const T *a,或者 T const *a,這二者都是同樣的,主要看const位於*的左邊仍是右邊,這裏再也不贅述,主要來看一下當const修飾類的成員函數時,成員函數有什麼特色。
http://www.javashuo.com/article/p-koqaveky-ep.html

html

類的成員函數後面加 const,代表這個函數不會對這個類對象的數據成員(準確地說是非靜態數據成員)做任何改變。

在設計類的時候,一個原則就是對於不改變數據成員的成員函數都要在後面加 const,而對於改變數據成員的成員函數不能加 const。因此 const 關鍵字對成員函數的行爲做了更加明確的限定:ios

(1)有 const 修飾的成員函數(指 const 放在函數參數表的後面,而不是在函數前面或者參數表內),只能讀取數據成員,不能改變數據成員;沒有 const 修飾的成員函數,對數據成員則是可讀可寫的。
(2)除此以外,在類的成員函數後面加 const 還有什麼好處呢?那就是常量(即 const)對象能夠調用 const 成員函數,而不能調用非const修飾的函數。

c++

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
class A
{
public:
    void f()
    {
        cout<<"non const"<<endl;
    } 
    void f() const
    {
        cout<<" const"<<endl;
    } 
};

int main(int argc, char **argv)
{
    A a;
    a.f();
    const A &b=a;
    b.f();
    const A *c=&a;
    c->f();
    A *const d=&a;
    d->f();
    A *const e=d;
    e->f();
    const A *f=c;
    f->f();
    return 0;
}

  注意:兩個成員函數若是隻是常量性不一樣,是能夠被重載的。看下面解釋的第二點:編程

C++的const類型成員函數(解釋爲何非const成員函數不能訪問const類對象的數據成員)

1. 在C++中只有被聲明爲const的成員函數才能被一個const類對象調用。

 在C++中,只有被聲明爲const的成員函數才能被一個const類對象調用。函數

若是要聲明一個const類型的類成員函數,只須要在成員函數列表後加上關鍵字const, 例如:this

class Screen {
    public:
        char get() const;
};

在類體以外定義const成員函數時,還必須加上const關鍵字,例如:spa

char Screen :: get() const {
    return _screen[_cursor];
} 

若將成員函數聲明爲const,則不容許經過其修改類的數據成員。 值得注意的是,若是類中存在指針類型的數據成員即使是const函數只能保證不修改該指針的值,並不能保證不修改指針指向的對象。例如:設計

class Name {
public:
void setName(const string &s) const;
private:
    char *m_sName;
};
void setName(const string &s) const {
    m_sName = s.c_str();      // 錯誤!不能修改m_sName;
for (int i = 0; i < s.size(); ++i) 
    m_sName[i] = s[i];    // 很差的風格,但不是錯誤的
}

 

2. const成員函數能夠被對應的具備相同形參列表的非const成員函數重載,例如:

class Screen {
public:
char get(int x,int y);
char get(int x,int y) const;
};
int main()
{
const Screen cs;
Screen cc2; 
char ch = cs.get(0, 0);  // 調用const成員函數  
ch = cs2.get(0, 0);     // 調用非const成員函數 
}

在這種狀況下,類對象的常量性決定調用哪個函數: 指針

  • const成員函數能夠訪問非const對象的非const數據成員,const數據成員,也能夠訪問const對象內的全部數據成員;
  • 非const成員函數只能夠訪問非const對象的任意的數據成員(不能訪問const對象的任意數據成員);(上述緣由可詳見C++Primer(5th)231頁。 在默認狀況下,this的類型是指向類類型很是量版本的常量指針,例如 Screen類中,this類型爲 Screen *cosnt。當在成員函數的後面加上const關鍵字時,隱式的將this指針修改成 const Screen *const 即指向類類型常量版本的常量指針。根據初始化原則,咱們不能將一個常量指針賦值給一個很是量指針)
  • 做爲一種良好的編程風格,在聲明一個成員函數時,若該成員函數並不對數據成員進行修改, 應儘量將該成員函數聲明爲const成員函數。

2. const修飾的是誰?

 const成員函數的寫法有兩種code

  一、void fun(int a,int b) const{}

  二、void const fun(int a,int b){}

這兩種寫法的本質是:void fun (const 類 *this, int a,int b);

const修飾的不是形參a和b;const修飾的是屬性this->a和this->b。與const所寫的位置無關。

爲何?

由於c++對類的this指針作了隱藏,本質上,const指針修飾的是被隱藏的this指針所指向的內存空間,修飾的是this指針

 

總結:

1)const成員函數能夠訪問非const對象的非const數據成員、const數據成員,也能夠訪問const對象內的全部數據成員;

2)非const成員函數能夠訪問非const對象的非const數據成員、const數據成員,但不能夠訪問const對象的任意數據成員

3)做爲一種良好的編程風格,在聲明一個成員函數時,若該成員函數並不對數據成員進行修改操做,應儘量將該成員函數聲明爲const 成員函數。

4)若是隻有const成員函數,非const對象是能夠調用const成員函數的。當const版本和非const版本的成員函數同時出現時,非const對象調用非const成員函數。

  

補充:

> 類中的const成員變量都要放在初始化列表之中進行
  > const數據成員
  > 引用數據成員
  > 對象數據成員(內置類)

 

  const成員函數
  > void print() const => const 類名 * const this
  > 在其內部是不能修改數據成員
  > 只能調用const成員函數,不能調用非const成員函數
  > const對象只能調用const成員函數,必需要提供一個const版本的成員函數

 

const成員函數和成員變量這一塊的邏輯容易混亂!

相關文章
相關標籤/搜索