函数声明和函数定义中的默认参数浅析

默认参数是存在于函数的声明中,还是函数的定义中呢?
    我在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、默认参数的语句所在的位置需要在主调函数的语句的前面。
同样适用于类的普通成员函数。
时间: 2024-10-02 12:59:26

函数声明和函数定义中的默认参数浅析的相关文章

【转】深入理解C++的动态绑定和静态绑定 &amp; 不要重定义虚函数中的默认参数

为了支持c++的多态性,才用了动态绑定和静态绑定.理解他们的区别有助于更好的理解多态性,以及在编程的过程中避免犯错误.需要理解四个名词:1.对象的静态类型:对象在声明时采用的类型.是在编译期确定的.2.对象的动态类型:目前所指对象的类型.是在运行期决定的.对象的动态类型可以更改,但是静态类型无法更改.关于对象的静态类型和动态类型,看一个示例: class B { } class C : public B { } class D : public B { } D* pD = new D();//p

“函数声明”、“函数原型”与“函数定义”辨析

最近在看一本关于C的书,对函数声明和函数定义的定义很是模糊,分不清楚,百度了一下,发现一篇帖子写的很是不错,转载过来: 原文: 对函数的“定义”和“声明”不是一回事.函数的定义是指对函数功能的确立,包括指定函数名,函数值类型.形参及其类型以及函数体等,它是一个完整的.独立 的函数单位.而函数的声明的作用则是把函数的名字,函数类型以及形参的类型.个数和顺序通知编译系统,以便在调用该函数时进行对照检查(例如,函数名是否 正确,实参与形参的类型和个数是否一致),它不包括函数体.————谭浩强 ,<C程

函数声明和函数定义的区别

1 "函数的声明"指函数的返回值类型 函数名 函数的参数列表:"函数的定义"不仅包括以上,还包括函数体的实现. 2 "函数的定义"如果在调用函数行的前面时,则不需要函数声明.否则需要在该调用函数行的前面进行函数声明. 3 如果一个函数中有多个默认参数,则形参分布中,默认参数应从右至左逐渐定义.当调用函数时,只能向左匹配参数.. 1 #include "stdafx.h" 2 3 int _tmain(int argc, _TC

javascript中函数声明和函数表达式浅析

记得在面试腾讯实习生的时候,面试官问了我这样一道问题. //下述两种声明方式有什么不同 function foo(){}; var bar = function foo(){}; 当初只知道两种声明方式一个是函数声明一个是函数表达式,具体有什么不同没能说得很好.最近正好看到这方面的书籍,就想好好总结一番. 在ECMAScript中,有两个最常用的创建函数对象的方法,即使用函数表达式或者使用函数声明.对此,ECMAScript规范明确了一点,即是,即函数声明 必须始终带有一个标识符(Identif

JS中函数声明与函数表达式的不同

Js中的函数声明是指下面的形式: function functionName(){ } 这样的方式来声明一个函数,而函数表达式则是类似表达式那样来声明一个函数,如: var functionName = function(){ } 可能很多朋友在看到这两一种写法时会产生疑惑,这两种写法差不多,在应用中貌似也都是可行的,那他们有什么差别呢? 事实上,js的解析器对函数声明与函数表达式并不是一视同仁地对待的.对于函数声明,js解析器会优先读取,确保在所有代码执行之前声明已经被解析,而函数表达式,如同

javascript中函数声明与函数表达式的区别

javascript中声明函数的方法有两种:函数声明式和函数表达式.究竟他们用起来有什么区别呢? 区别如下: (1).以函数声明的方法定义的函数,函数名是必须的,而函数表达式的函数名是可选的. (2).以函数声明的方法定义的函数,函数可以在函数声明之前调用,而函数表达式的函数只能在声明之后调用. (3).以函数声明的方法定义的函数并不是真正的声明,他们仅仅可以出现在全局中或者嵌套在其它函数中. 下面来看具体的例子吧.下面这两种方式有什么区别吗? function boo(){}; var bar

C++成员函数实现在类定义中与在类定义外的区别(Windows下直接使用g++)

在上篇文章<inline的另一用处>中,提到函数实现在类定义中与类定义外的区别. 现在先看个实验: a.cpp: [cpp] view plain copy #ifndef TEST_H #define TEST_H class A{ public: int fun(int x){ return (x*x+1000); } }; #endif void tt() { } b.cpp: [cpp] view plain copy class A{ public: int fun(int x);

[js]变量声明、函数声明、函数定义式、形参之间的执行顺序

一.当函数声明和函数定义式(变量赋值)同名时 function ledi(){ alert('ledi1'); }; ledi(); var ledi = function (){ alert('ledi2'); }; ledi(); 执行顺序: var ledi: function ledi(){ alert('ledi1'); }; //预编译结束 ============== ledi(); ledi = function (){ alert('ledi2'); }; ledi(); 函数

【JavaScript】Javascript中的函数声明和函数表达式

Javascript有很多有趣的用法,在Google Code Search里能找到不少,举一个例子: <script> ~function() { alert("hello, world."); }(); </script> 试一下就知道这段代码的意思就是声明一个函数,然后立刻执行,因为Javascript中的变量作用域是基于函数的,所以这样可以避免变量污染,但这里的位运算符『~』乍一看让人摸不到头脑,如果去掉它再运行则会报错:SyntaxError. 在阐述