首页 > 代码库 > C++函数默认参数(转)

C++函数默认参数(转)

在代码中使用到了函数的默认参数,在函数的定义和实现中都填写的默认参数,结果出现了错误:

代码:

 1 #ifndef FIRSTPAGE_H 2 #define FIRSTPAGE_H 3  4 #include <QWizardPage> 5 #include "ui_firstdialog.h" 6  7 class FirstPage : public Ui::FirstDialog, public QWizardPage 8 { 9 public:10     FirstPage(QWidget *parent = 0);11 };12 13 #endif // FIRSTPAGE_H

 

1 #include "fifthpage.h"2 3 FifthPage::FifthPage(QWidget *parent = 0) :4     QWizardPage(parent)5 {6 }

当去掉了实现文件中的默认参数值时,通过了编译,于是就考虑是不是因为同时在定义文件中和实现文件中都填写了默认参数造成了这个错误。在网上搜到一篇讲的比较详细的文章: 函数声明和函数定义中的默认参数浅析

默认参数是存在于函数的声明中,还是函数的定义中呢?

    我在VS6.0和VS2008下做了如下实验,并做出了简单的总结,有不足或者不准确的地方,欢迎大家拍砖,我会及时修正相关内容。
 
    实验一:默认参数不能同时存在于函数声明和函数定义中
 
  1. #include <iostream>
  2. #include <tchar.h>
  3. using namespace std;
  4.  
  5. void SetHeight(double dHeight = 183.5);
  6.  
  7. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
  8. {
  9.     SetHeight(181.5);
  10.     return 1;
  11. }
  12.  
  13. void SetHeight(double dHeight = 183.5)
  14. {
  15.     cout << _T("身高为:") << dHeight << endl;
  16. }
然后调整一下顺序(本文的例子只用于实验,并不侧重于代码本身是否有意义):
 
  1. #include <iostream>
  2. #include <tchar.h>
  3. using namespace std;
  4.  
  5. void SetHeight(double dHeight = 183.5);
  6. void SetHeight(double dHeight = 183.5)
  7. {
  8.     cout << _T("身高为:") << dHeight << endl;
  9. }
  10. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
  11. {
  12.     SetHeight(181.5);
  13.     return 1;
  14. }
两处代码编译的时候,编译器都会报告如下错误:
error C2572: ‘SetHeight‘ : redefinition of default parameter : parameter 1,see declaration of ‘SetHeight‘
 
实验一小结:编译器不允许默认参数同时存在于声明和定义中,之所以这个做,个人猜测:
1、没必要,声明和定义都有默认参数相比于声明或者定义中一处有默认参数,没什么多余的意义。
2、容易犯错,就上例而言,假如在声明中设置默认参数值为183.5,在定义中设置默认参数值为167.5,将导致错误的产生,所以,只允许其中一处设置默认参数可以避免这种形式的错误。
 
    实验二:默认参数的所在的位置需要在调用者的前面
 
  1. #include <iostream>
  2. #include <tchar.h>
  3. using namespace std;
  4.  
  5. void SetHeight(double dHeight = 183.5);
  6.  
  7. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
  8. {
  9.     SetHeight();
  10.     return 1;
  11. }
  12.  
  13. void SetHeight(double dHeight)
  14. {
  15.     cout << _T("身高为:") << dHeight << endl;
  16. }
上述代码编译通过。
 
  1. #include <iostream>
  2. #include <tchar.h>
  3. using namespace std;
  4.  
  5. void SetHeight(double dHeight);
  6.  
  7. void SetHeight(double dHeight = 183.5)
  8. {
  9.     cout << _T("身高为:") << dHeight << endl;
  10. }
  11.  
  12. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
  13. {
  14.     SetHeight();
  15.     return 1;
  16. }
上述代码编译通过。
 
  1. #include <iostream>
  2. #include <tchar.h>
  3. using namespace std;
  4.  
  5. void SetHeight(double dHeight = 183.5);
  6.  
  7. void SetHeight(double dHeight)
  8. {
  9.     cout << _T("身高为:") << dHeight << endl;
  10. }
  11.  
  12. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
  13. {
  14.     SetHeight();
  15.     return 1;
  16. }
上述代码编译通过。
 
  1. #include <iostream>
  2. #include <tchar.h>
  3. using namespace std;
  4.  
  5. void SetHeight(double dHeight);
  6.  
  7. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
  8. {
  9.     SetHeight();
  10.     return 1;
  11. }
  12.  
  13. void SetHeight(double dHeight = 183.5)
  14. {
  15.     cout << _T("身高为:") << dHeight << endl;
  16. }
上述代码在编译的时候,编译器报告如下错误:
error C2660: ‘SetHeight‘ : function does not take 0 parameters
 
实验二小结:编译通过的代码都有一个共同点,无论默认参数在函数声明语句中还是在函数定义语句中,默认参数的位置都在调用该函数的语句之前(代码的编写顺序),而编译失败的代码是因为调用函数的语句在默认参数所在的语句之后,由此得出一个结论:默认参数的语句所在的位置需要在主调函数的语句的前面。
 
    实验三:函数的声明和定义分别位于不同文件中的默认参数规则
 
  1. // Head.h
  2. #pragma once
  3. #include <tchar.h>
  4. #include <iostream>
  5. using namespace std;
  6.  
  7. void SetHeight(double dHeight = 183.5);
 
  1. //Body.cpp
  2. #include "Head.h"
  1. void SetHeight(double dHeight)
  2. {
  3.     cout << _T("身高为:") << dHeight << endl;
  4. }
 
  1. //Main.cpp
  2. #include "Head.h"
  3.  
  4. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
  5. {
  6.     SetHeight();
  7.     return 1;
  8. }
上述代码编译通过,因为Main.cpp中包含了Head.h,等价于将Head.h中的内容拷贝到#include"Head.h"的位置,所以在_main函数中的SetHeight()语句执行之前,就找到了带默认参数的函数声明。
 
  1. // Head.h
  2. #pragma once
  3. #include <tchar.h>
  4. #include <iostream>
  5. using namespace std;
  6.  
  7. void SetHeight(double dHeight);
  1. //Body.cpp
  2. #include "Head.h"
  3.  
  4. void SetHeight(double dHeight = 183.5)
  5. {
  6.     cout << _T("身高为:") << dHeight << endl;
  7. }
  1. //Main.cpp
  2. #include "Head.h"
  3.  
  4. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
  5. {
  6.     SetHeight();
  7.     return 1;
  8. }
上述代码在编译的时候,编译器报告如下错误:
error C2660: ‘SetHeight‘ : function does not take 0 parameters
由此,我猜测:编译器在编译到_tmain函数的SetHeight()语句的时候,只找到了SetHeight的声明,并以此判断出函数参数有错误。所以,SetHeight函数的定义部分并未出现在主调函数语句之前。
 
  1. // Head.h
  2. #pragma once
  3. #include <tchar.h>
  4. #include <iostream>
  5. using namespace std;
  6.  
  7. void SetHeight(double dHeight);
  1. //Body.cpp
  2. #include "Head.h"
  3.  
  4. void SetHeight(double dHeight = 183.5)
  5. {
  6.     cout << _T("身高为:") << dHeight << endl;
  7. }
  8.  
  9. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
  10. {
  11.     SetHeight();
  12.     return 1;
  13. }
上述代码编译通过。
 
实验三小结:函数的声明和定义位于不同文件中的默认参数的规则同样要遵循实验二的结论。
 
上述的三个实验得出的两条结论:
1、编译器不允许默认参数同时存在于声明和定义中。
2、默认参数的语句所在的位置需要在主调函数的语句的前面。
同样适用于类的普通成员函数。