我們知道如果不希望改變某個變量的值就用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修飾字段,這樣就只能讀不能修改了.