2014-11-03 88 views
4

對於下面的代碼:非靜態const數據成員的要點是什麼?

class A 
{ 
public: 
    const int cx = 5; 
}; 

這裏,CX的實例將爲A的每一個對象,它似乎是一種浪費我的創建,爲CX不能進行修改。其實,我沒有看到編譯器不應該強制const數據成員靜態的任何理由。任何人都可以向我解釋這個嗎?

+0

有可能是RAII應用程序...... – IdeaHat 2014-11-03 18:01:14

+0

這就像說說編譯器應該堅持所有靜態數據是不變的。有些人喜歡他們的成員不變 – Creris 2014-11-03 18:02:52

+0

您可能仍然添加其他構造函數來爲'cx'設置不同的值。 – Jarod42 2014-11-03 18:03:27

回答

8

對於所有實例,const數據成員不必相同。你可以在構造函數中初始化它。

class A 
{ 
public: 
    A(int n) :cx(n) {} 

    const int cx; 
}; 

int main() 
{ 
    A a1(10); 
    A a2(100); 
} 
+0

注意,您必須在初始化程序列表中初始化它。當你進入構造函數的主體時,已經太晚了。即失敗:'A(int n){cx = n; }' – dgnuff 2014-11-03 18:53:17

6

其實,我看不出有任何理由爲什麼不編譯器應該推行使 一個const數據成員靜態的。

你認爲cx可能在構造函數在運行時已知的值進行初始化 - 和A不同實例之間變化?
const成員對他們進行分配是不可能的,但有時會讓一個無法改變其初始值的成員證明是有用的。

絕對不是最好的例子,但說明的想法:

struct Multiplier 
{ 
    const int factor; 

    Multiplier(int factor) : factor(factor) {} 

    int operator()(int val) const 
    { 
     return val * factor; 
    } 
}; 

std::vector<int> vec{1, 2, 3}; 
std::vector<int> vec2; 

int i; 
std::cin >> i; 

std::transform(std::begin(vec), std::end(vec), 
       std::back_inserter(vec2), Multiplier(i)); 

// vec2 contains multiples of the values of vec 
1

如果該值被初始化爲一個常數,在你的榜樣, 它可能會更好,這是靜態的。但這並不總是 的情況;這是相當頻繁有類似:

class Matrix 
{ 
    const int myRowCount; 
    const int myColumnCount; 
    std::vector<double> myData; 
    // ... 
public: 
    Matrix(int rows, int columns) 
     : myRowCount(rows) 
     , myColumnCount(columns) 
     , myData(rows * columns) 
    { 
    } 
    // ... 
}; 

在這種情況下,const明確表達了的 行和列在任何給定的情況下的數量不會改變。 (在 另一方面,它阻止默認賦值運算符從生成 ,這可能會也可能不是一件好事。)

0

使用非靜態const成員有一些限制。

假設有Employee類。 首先,雖然編譯器可以生成正確工作的拷貝構造函數,但它不能生成賦值運算符。如果一個程序創建兩個Employee對象e1和e2,則語句e1 = e2將導致編譯器診斷。這個賦值是無效的,因爲它隱含地試圖改變const成員的值。 雖然你可以通過拋棄const_ness來賦值賦值操作符,但是這不是一個好主意。

另一個限制是很難爲這個類提供一個有用的默認構造函數。如果你想創建Employee對象的數組,那麼默認的構造函數是很重要的。定義一個默認的構造函數有點棘手;要記住的主要事情是const的非靜態數據成員在構造函數的初始化列表中初始化 - 並且您必須初始化它們全部。默認構造函數必須將dob字段設置爲某個值,並且此值不能隨後更改。所以構建的陣列幾乎沒用

相關問題