2017年3月4日 星期六

const 屬性規則與可能出現的問題

const 屬性規則與可能出現的問題

tags: C++ Concept

規則

  • 引入參數為 const 也可以導入 非const 版本
  • 物件帶 const 屬性,使用函數時只能呼叫 const 版本函式
  • 一般條件下 const 屬性必須被從頭到尾繼承
  • 使用 const_cast<typename> 可移除 const 屬性
  • 被宣告為 const 屬性只能在宣告時賦值

宣告類別時的放置位置

const 的放置位置在宣告時可以跟型別換位置
這樣有助於提升閱讀,不然一整排開頭都 const 還要往右邊看一下才知道是什麼型別。
const int i;
int const i;

要注意的是當指針符號(derefrence)加入時有些微的不同。
可以分成3種不同
const int *i;
int const *i;

int* const i;

const int* const i;

分辨方式簡單用一條規則,看const右邊有沒有 *
const 有修飾到 * 所以 * 不可被修改
const int *i;
int const *i;

*i=0; // Error 不可被修改

const 沒有修飾到 * 所以 沒有 * 不可被修改
int * const i;
i=0;  // Error 不可被修改

指針本身指針所指 之處都不能變動
const int* const i;
i=0;  // Error 不可被修改
*i=0; // Error 不可被修改
可能還有其他樣式大概就這條主規則去判定

宣告函式時的放置位置

回傳型別可以交換位置
指的是傳出的參考在這之後,可不可以被更改
const int & fun(){...}
int const & fun(){...}

放置在引入參數
可以接收 const非const 參數
void fun(const int i){
    i=0; // Error 不可修改
}

const int i=0;
fun(i);

int j=0;
fun(j);

放置在引入參數後(成員函式)

本地成員(this)不可被修改
void T::fun() const{
    this->data = 0; // Error 不可修改
}

這裡可能會遇到一個問題
存取函式成員,如果定義了非const版本,建議補上const版本
int & T::get(){...}
在某些狀況可能會用到 const 版本
void T::add(const T& obj){
    this->get() += obj.get()
}
報錯
error: passing '...' as '...' argument discards qualifiers [-fpermissive]
因為引入的參數是有 const 修飾,他找不到 const版本 的函式可用。
const屬性必須被繼承下去

 放棄const修飾
void T::add(T& obj){
            ^
    this->get() += obj.get()
}

多載 const 版本的 get()
int & T::get() const{...}
                 ^
重寫兩份一樣的代碼的問題可以參考:重載operator[]

移除 const 屬性
void T::add(const T& obj){
    this->get() += const_cast<T&>(obj).get()
}
多載的可能是比較好的解法,不會干預到其他地方。

const 屬性只能在宣告時賦值

const int i=0;
const int i;
i=0; // Error 不可修改

成員函式具備const屬性如何初始化

成員具備const屬性
class T {
    T(int num){
        this->i = num; // Error 不可修改
    }
    const int i;
};

使用初值建構(initializer)
class T {
    T(int num): i(num){}
    const int i;
};

沒有留言:

張貼留言