函數聲明和函數定義中的默認參數淺析


默認參數是存在於函數的聲明中,還是函數的定義中呢?
    我在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、默認參數的語句所在的位置需要在主調函數的語句的前面。 同樣適用於類的普通成員函數。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM