發新話題

C++ Gossip - 物件基礎《封裝》const 與 mutable

C++ Gossip - 物件基礎《封裝》const 與 mutable

假設您設計了一個Ball類別:
  • Ball.h
#include <string>
using namespace std;

class Ball {
public:
    Ball();
    Ball(double, const char*);     
    Ball(double, string&);
   
    double radius() {
        return _radius;
    }
   
    string& name() {
        return _name;
    }
   
    void radius(double radius) {
         _radius = radius;
    }
   
    void name(const char *name) {
         _name = name;
    }
        
    void name(string& name) {
         _name = name;
    }
   
    double volumn() {
        return (4 / 3 * 3.14159 * _radius * _radius * _radius);
    }
   
private:
    double _radius; // 半徑
    string _name;  // 名稱
};
假設您現在設計了一個somefun()函式:
void somefun(const Ball &ball) {
     ball.radius();
}


在函式的參數列上,您使用const宣告了ball參數,在編譯時會出現以下的訊息:
passing `const Ball' as `this' argument of `double Ball::radius()' discards qualifiers


由於參數列上ball使用了const來宣告,這表示您不可以更動ball實例的狀態,也就是不得(在呼叫函式時)更動ball的資料成員,為了讓編譯器得知這項訊息,您要在所呼叫的函式上加上const,例如:
void radius() const {
    return _radius;
}


編譯器會檢查每個被標示為const的成員函式,看看當中的陳述有無更動物件的資料成員。

另一方面還有一個問題,假設您在somefun()函式中如下呼叫:
void somefun(const Ball &ball) {
     ball.name();
}


則編譯時會出現以下的錯誤訊息:
`const Ball' as `this' argument of `std::string& Ball::name()' discards qualifiers


即使您在name()函式後加上const,編譯時照樣無法通過,原因在於name()是以傳參考的方式傳回,而不是以傳值的方式傳回,由於以傳參考的方式傳回,接受傳回值的物件可以直接更改傳回值,因而影響被呼叫物件的狀態,為了保證傳回值不被修改,您要在傳回值宣告上加上const,也就是:
const string& name() const {
    return _name;
}

有時候您會希望大部份成員在const成員函式中不被更改,但少數幾個資料成員允許它們在const成員函式中被更動,因為這些資料成員被變動並不被視為改變了物件的狀態,這時候您可以在該資料成員宣告時加上mutable,表示對該成員的變動並不代表對物件狀態的改變,例如:
class SomeClass {
public:
    ....
    double increment() const {
        return _index++;
     }

private:
    ....
    mutable double _index;
};

TOP

發新話題

本站所有圖文均屬網友發表,僅代表作者的觀點與本站無關,如有侵權請通知版主會盡快刪除。