我們知道如果不希望改變某個變數的值就用const修飾它,讓它變為常量.基本類型和指標類型都能用const來修飾.數組也可以用const來修飾.
那你自然要問我們把class執行個體化成一個對象後,如果不希望修改對象中的成員變數,讓對象變得像個常量一樣該咋整呢?
你首先自然會想到把類中所有的成員變數都用const修飾不就得了.其實這確實是個辦法拉,但是如果我們只是想某個類的一個執行個體對象弄得像常量啊.你這樣用const整就真成了常量了,所有類的執行個體都只能當常量來處理了.這顯然不行拉.
其實很簡單,我們只要執行個體化類時加個const修飾下就OK,但是由於類不是個簡單的類型.所以還涉及到一些特殊的操作.還是舉個簡單的例子看下.
class MyClass
{
public:
int age;
string name;
MyClass(int num,string str)
{
age = num;
name = str;
}
void Test() { Print(); }
void Print() const
{
std::cout<<name<<endl;
}
~MyClass(void);
};
const MyClass my(110,"arwen"); //執行個體化類時用const修飾.
my.age = 911; //這樣會出錯,既然用const修飾了肯定就變得像常量一樣,不能改變成員變數的值了.
my.Print(); //正確執行
my.Test(); //出錯了
為啥調用my.Test()時會出錯呢? 這就是特殊的地方了.當用const修飾一個對象後,此對象就只能調用const修飾的函數了(const必須放到函數變後面).而一般的函數是不能被調用了.
為啥這樣其實很簡單,出於一致性考慮.既然不讓直接修改成員變數了.那任何潛在的有可能修改成員變數的操作都就禁止.因為一般函數中有可能會修改了成員變數值.所以乾脆禁止調用.
函數後面加個const是代表啥意思呢.它是代表在此函數中不能修改成員變數的值.例如
void Print() const { age = 456;} //這樣會出錯.當然你如果在函數中修改其他不是成員變數的值就沒問題.
const修飾的函數中如果有調用到其他函數,那被調用的函數也只能是後面被const修飾的.當然一般函數調用const修飾的函數是沒啥限制的.
所以通過當用const修飾對象後
1.不能像my.age = 911這樣直修改成員變數
2.對象只能調用被const修飾的函數
3.被const修飾的函數中不能修改成員變數,且它也只能調用其他也被const修飾的函數.
通過這三點確保了成員函數在任何情況下都不會被修改.用建構函式賦值後就一直不變.
上面說到的用const修飾函數也可以單獨用,不一定和const修飾對象配合用.單獨用的話約定也是一樣,函數中不能修改成員變數
上面說的是在C++中,那在C#中呢?
首先C#中一般把成員變數叫作欄位.跟C++不同,C#中可以直接給欄位賦值的.所以用const修飾類中的欄位,然後賦值是沒問題的.但顯然我們很多時候是希望用建構函式來賦值的.那咋整呢?也像C++一樣用個const修飾下就OK了嗎.那不行.因為用const修飾參考型別時只能給賦值為null,那等於說那對象沒任何用處了.當然C#自然有其他動作可以達到類似的效果.那就是通過屬性加許可權修飾符.
class MyClass
{
private int age;
private string name;
public int Age {
get{return age;}
}
public int Name {
get{return name;}
}
MyClass(int num,string str)
{
age = num;
name = str;
}
}
如果不希望使用者修改欄位.就把欄位全部設為private的.然後用屬性提供個介面.只有讀的許可權,不能修改.只有建構函式能賦值一次.那你可能會問其他成員函數會修改啊?
這就需要遵守一個約定了,就是類中其他函數別直接去用欄位,也只是去用屬性Age,Name.當然這隻是推薦的作法,如果你實在想去直接用欄位,去修改了.那就沒辦法了啊.
反正C#中使用了屬性,推薦的作法就是在成員函數中直接用屬性,別直接用欄位了.
另外還有個辦法就是用readonly修飾欄位,這樣就只能讀不能修改了.