...
預設參數是存在於函數的聲明中,還是函數的定義中呢? 我在VS6.0和VS2008下做瞭如下實驗,並做出了簡單的總結,有不足或者不准確的地方,歡迎大家拍磚,我會及時修正相關內容。 實驗一:預設參數不能同時存在於函數聲明和函數定義中。 #include <iostream> #include <tchar.h> using namespace std; void SetHeight(double dHeight = 183.5); int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { SetHeight(181.5); return 1; } void SetHeight(double dHeight = 183.5) { cout << _T("身高為:") << dHeight << endl; } 然後調整一下順序(本文的例子只用於實驗,並不側重於代碼本身是否有意義): #include <iostream> #include <tchar.h> using namespace std; void SetHeight(double dHeight = 183.5); void SetHeight(double dHeight = 183.5) { cout << _T("身高為:") << dHeight << endl; } int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { SetHeight(181.5); return 1; } 兩處代碼編譯的時候,編譯器都會報告如下錯誤: error C2572: 'SetHeight' : redefinition of default parameter : parameter 1,see declaration of 'SetHeight' 實驗一小結:編譯器不允許預設參數同時存在於聲明和定義中,之所以這個做,個人猜測: 1、沒必要,聲明和定義都有預設參數相比於聲明或者定義中一處有預設參數,沒什麼多餘的意義。 2、容易犯錯,就上例而言,假如在聲明中設置預設參數值為183.5,在定義中設置預設參數值為167.5,將導致錯誤的產生,所以,只允許其中一處設置預設參數可以避免這種形式的錯誤。 實驗二:預設參數的所在的位置需要在調用者的前面 #include <iostream> #include <tchar.h> using namespace std; void SetHeight(double dHeight = 183.5); int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { SetHeight(); return 1; } void SetHeight(double dHeight) { cout << _T("身高為:") << dHeight << endl; } 上述代碼編譯通過。 #include <iostream> #include <tchar.h> using namespace std; void SetHeight(double dHeight); void SetHeight(double dHeight = 183.5) { cout << _T("身高為:") << dHeight << endl; } int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { SetHeight(); return 1; } 上述代碼編譯通過。 #include <iostream> #include <tchar.h> using namespace std; void SetHeight(double dHeight = 183.5); void SetHeight(double dHeight) { cout << _T("身高為:") << dHeight << endl; } int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { SetHeight(); return 1; } 上述代碼編譯通過。 #include <iostream> #include <tchar.h> using namespace std; void SetHeight(double dHeight); int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { SetHeight(); return 1; } void SetHeight(double dHeight = 183.5) { cout << _T("身高為:") << dHeight << endl; } 上述代碼在編譯的時候,編譯器報告如下錯誤: error C2660: 'SetHeight' : function does not take 0 parameters 實驗二小結:編譯通過的代碼都有一個共同點,無論預設參數在函數聲明語句中還是在函數定義語句中,預設參數的位置都在調用該函數的語句之前(代碼的編寫順序),而編譯失敗的代碼是因為調用函數的語句在預設參數所在的語句之後,由此得出一個結論:預設參數的語句所在的位置需要在主調函數的語句的前面。 實驗三:函數的聲明和定義分別位於不同文件中的預設參數規則 // Head.h #pragma once #include <tchar.h> #include <iostream> using namespace std; void SetHeight(double dHeight = 183.5); //Body.cpp #include "Head.h" void SetHeight(double dHeight) { cout << _T("身高為:") << dHeight << endl; } //Main.cpp #include "Head.h" int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { SetHeight(); return 1; } 上述代碼編譯通過,因為Main.cpp中包含了Head.h,等價於將Head.h中的內容拷貝到#include"Head.h"的位置,所以在_main函數中的SetHeight()語句執行之前,就找到了帶預設參數的函數聲明。 // Head.h #pragma once #include <tchar.h> #include <iostream> using namespace std; void SetHeight(double dHeight); //Body.cpp #include "Head.h" void SetHeight(double dHeight = 183.5) { cout << _T("身高為:") << dHeight << endl; } //Main.cpp #include "Head.h" int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { SetHeight(); return 1; } 上述代碼在編譯的時候,編譯器報告如下錯誤: error C2660: 'SetHeight' : function does not take 0 parameters 由此,我猜測:編譯器在編譯到_tmain函數的SetHeight()語句的時候,只找到了SetHeight的聲明,並以此判斷出函數參數有錯誤。所以,SetHeight函數的定義部分並未出現在主調函數語句之前。 // Head.h #pragma once #include <tchar.h> #include <iostream> using namespace std; void SetHeight(double dHeight); //Body.cpp #include "Head.h" void SetHeight(double dHeight = 183.5) { cout << _T("身高為:") << dHeight << endl; } int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { SetHeight(); return 1; } 上述代碼編譯通過。 實驗三小結:函數的聲明和定義位於不同文件中的預設參數的規則同樣要遵循實驗二的結論。 上述的三個實驗得出的兩條結論: 1、編譯器不允許預設參數同時存在於聲明和定義中。 2、預設參數的語句所在的位置需要在主調函數的語句的前面。 同樣適用於類的普通成員函數。