文章目錄
函數傳回值
我們定義函數時會指定一個傳回值類型,那在函數體中必須返回一個匹配的類型,或者隱式轉換後能匹配的類型.不過有時存在這樣的情況,如果函數體中存在一些分支語句,有些情況是可以返回一個值,但有時不會傳回值.還是舉個例子吧.
有如下C++函數
int FunArwen(int a , int b)
{
if(a < b)
return 888;
}
很顯然,上面的函數有時會返回一個值,但有時又不會.
int result = FunArwen(4,5); //這時結果是888;
int res = FunArwen(5,4);
//這時函數不會有傳回值,不過我在VS中運行得到res為5,貌似返回了第一個參數的值.不知道為啥是這個值,沒太搞懂.
//不過反正這肯定是個錯誤的結果.
在C++中上面的函數編譯時間會有一個警告資訊"not all control paths return a value", 而在C#中上面的函數不能通過編譯的,會報錯,"not all code paths return a value".
你必須寫成 if (a < b) return 888 ;
else return 44;
或者if(a < b) return 888; return 444;
這樣才能編譯通過
C#針對C++中的很多地方都做了一些改進,多做了一些檢查.使你寫出來的代碼更不容易出錯.其實一個程式設計語言的發展很多時候關注的一是,簡化一些複雜的文法,使你能用更少的代碼實現更多的功能.另一個是多做一些檢查,要編譯期間就給你檢查出一些錯誤來.當然準確的講有些錯誤也不是真正的錯誤,只要有潛在的犯錯可能就當作錯誤處理了.
我們平時不是常講軟體測試嘛,其實編譯器做的工作也算是測試的一種,給你把代碼中的語法錯誤找出來.如果任何錯誤都能在編譯期間都找出來自然是最完美的,不過編譯器可沒這麼聰明.很多執行階段錯誤它是沒法檢測出來的.
C++返回局部函數體中局部變數指標或引用的問題
另外值得注意的是在C++中如果返回結果是函數體中的局部指標或參考型別.則會出錯,因為函數體中的局部變數一超過範圍就會被釋放了.所以指標就變成野指標了.不知道指到哪去了.舉個例子
int* GetResult( )
{
int num = 110;
int* ip = #
return ip;
}
int* p = GetResult(); //這樣做是錯誤的,不過有時錯誤的操作也會得到正確的結果.
//你運行時可能出現執行階段錯誤,可能運行正確得到個錯誤的結果,有時還可能得到正確的結果.反正我在VS中試的時候是得到個正確的結果的.
因為num超出範圍之後就告訴系統那塊記憶體它不要了,系統可以把那記憶體配置給別人用了.不過如果那記憶體暫時還沒被分給誰,那裡面的值還仍然在,所以你通過指標去訪問那個值時可能還能得到個正確的值
預設實參
假如某個函數的參數有很多個,我們調用時要傳那麼多個參數進去非常麻煩,而且有些參數不那麼重要,我們整個啥預設值就行.你首先想到的可能是來個函數重載,整很多個函數出來,但參數個數都不一樣.顯然這確實是一個辦法.但實現的不夠優美.在C++中有個預設實參的做法能更好的解決這問題.舉例
void Register(string userName = "打醬油的"
,string pwd = "123"
, int age = 18
)
{
//do something
}
這樣我們調用函數時可以像下面那樣
Register();
Register("arwen");
Register("arwen","911");
Register("weiwen","110",24);
上面那樣調用都正確,不過你這樣調用就不行
Register("wei", 24); //會出錯.因為系統是從左至右去匹配.你傳兩個參數它只會去匹配userName和pwd
C#中沒有預設實參
不過有點遺憾的是C# 2.0, 3.0中都沒有提供這個功能.據說c# 4.0有提借這功能.不過我還從沒用過4.0.微軟的東西更新太快,要老想去跟著趕時髦會很累的啊.還是老實的把基礎打好再說
This 指標
舉個例子,有C++類Arwen
class Arwen
{
private:
int age;
int height;
public:
void SetAge(int age)
{
this ->age = height;
}
void SetHeight(int hgt)
{
height = hgt;
}
}
Arwen wen;
int hgt = 111;
wen.SetHeight(hgt); //我們知道每個類的函數跟static變數一樣是不屬於某個執行個體的,所以的執行個體對象都使用共一個函數.函數是儲存在代碼區.那我們這樣調用函數時,怎麼能找到函數呢?實際上你像上面這樣調用一個函數時編譯器會預設把它 轉換成
Arwen::SetHeight(&wen , hgt);
然後給height賦值就是這樣 wen.height = hgt; //預設情況都是給自成員變數前加個執行個體對象做首碼.&wen也就是this指標了.
但如果成員變數和傳的參數同名了就必須顯式加this指標.
像SetAge中 this->age = age;
const函數
我們可以在函數後面加個const,例如void SetAge(int age) const { this->age = age;}
Arwen wen;
int age = 222;
wen.SetAge(age); //此時出錯了.
因為編譯器把上面的調用中的this指標轉化成指向const類型的指標了,所以不用this->age = age;這樣去修飾指標指向的值了.
C#中的this的用法和原理跟C++差不多.雖然C#中沒有指標的概念,但我猜實際上後台很多實現最終都是通過指標實現的.估計C#的編譯器也是用C++和C開發的吧.連微軟的操作操作都是C++和C開發的.