一. 函数特性
(1). 函数的原型
一个典型的函数由,返回值 函数名 形参 实现代码组成,其中参数根据需要 可以是 0~ n 个 ,而除去实现的其余部分就叫 函数的原型 如
int Add(int x, int y)
{
return (x+y);
}
其中 粗体 部分就是函数的原型,当函数没有形参时,圆括号为空 或 在圆括号里填入关键字 void 来表示,
void Say()
===
void Say(void)
当有返回值时,需用关键字
return 返回相应类型 ,
(2). 函数重载
函数重载 是为了使同一功能的函数能够接受多种不同组合的参数,增加其灵活性。定义重载很简单,只要函数 参数类型,传递方式,不同类型参数的顺序或个数和其他同名函数不同就可成功声明一个重载, 如
void Say ();
void Say (int x);
void Say (int &x);
void Say (const int &x);
void Say (int *x);
int Say (int *x); //error
int Say (int *x , string y);
int Say (string y,
int *x
);
可以看出
如果两个函数重载版本之间的区别只是返回值类型不同,这样是错误的,
形参为引用类型时,形参是否为
const , 也可以作为函数重载的条件, 但尽量不要这么做。
(3). 引用类型和值类型 形参
当形参不为 引用<&>或指针<*>时,该形参就为值类型形参,否则为 引用形参,
[学过 Java 或 C# 的看到这里可能会困惑, 其实 Java 或 C# 没有指针的语法,但其内部也是使用指针,像在 Java 中定义 类 是引用类型 如 String,在传递时,内部其实都是(强制)用指针操作。只是在语言级隐藏了,所以几种语言对 引用类型和值类型的定义其实是一致的 ]
函数处理
引用类型 和 值类型 的方式是不同的
- 当形参 为 值类型,传入实参时,会拷贝一个实参的副本,函数作用域内对该实参的一切操作都是对副本的操作,而不会影响实参本身。
- 当形参 为 引用类型 ,传入实参时,函数作用域内对该参数的操作,都是对实参本身的操作。
特别要注意的是 数组
- 在语言级数组名 默认会转换为 (本质上和指针并不相同,具体见本系列文章五 ) 指向数组首元素的常量指针,所以当形参为数组时,即便不使用 引用或指针操作符修饰,其也是引用类型
(4). C++重载的本质
其实重载只是 C++语言级的功能,当 <编译链接>时会将所有函数重命名,使其唯一,根据编译器不同链接时命名规则也有所不同, 一般都是 <命名空间+函数名+参数>, 你可以通过 <编译链接> 时生成的 .map文件查看更改后的函数名 (vs下要输出 map文件需设置: 项目-->属性 --> 配置属性 --> 链接器 --> 调试 --> 设置 映射文件的相关选项)
(5). C++重载的应用场景
重载的一个典型应用是 当函数有默认值时,可以提供一个完整参数版本, 再重载该函数并省略若干的参数,然后在该重载函数里调用完整参数版本。 如登陆场景,可以用自己的用户名登录
也可以用
默认游客身份登录
, 当用游客身份登录时只需调用其重载的无参版本即可。
char
defaultName[] =
"visitor"
;
char
defaultPwd[] =
"visitor"
;
void
Login(
char
name[],
char
pwd
[])
{
}
void
Login()
{
Login(defaultName,defaultPwd);
}
(6). 返回值为指针类型的函数
函数名前加 *号 时,表示该函数的返回值为 某个类型的指针
int tem = 10;
int *p = &tem;
int *p = &tem;
int *test(){ return p };
(7). 指向函数的指针
函数实质上保存一块连续的内存地址,我们只需要知道函数的首地址就可以调用它,
我们知道 指针可以指向任何可用的内存地址,自然也可以指向函数(首地址)。
要定义一个函数指针,只需将函数原型(签名)中函数名部分变为指针声明。并为该声明加上括
号。如 要声明 void Say(string str) 类型的指针
void
(*)(
string
)
然后让该指针指向函数的首地址
* (
void(*)(
string
) ) Say
在语言级上,函数名就是一个指向函数首地址的指针。知道了这一点上边的语句就不难理解。将函数名这个指针 转换为 刚才声明的 函数指针。
最后就是和调用普通函数一样调用函数指针,
( *(
void(*)(
string
) )Say) (
"参数"
);
这样括号复括号的写起来易错也不易读,所以可以用另外一种方式,将声明,初始化,调用它分开来写。这里用到了关键字 typedef。它的作用就是为 某类型 起一个别名,以便于书写
typedef
void
(*
py)(
string );
上边的语句就是 声明原型为有一个string类型参数且无返回值的函数指针。并为其起一个别名 py。
接下来初始化并调用
Py
spy = &Say;
spy(
"s2");
在这里省略不写取地址操作符,有些编译器上是可以编译的。但建议写上
二 函数特例
(1). 启动函数 main()
main()函数 有些书上叫 主函数 ,该函数是 C++程序 入口函数, 既 程序都是从main()开始执行.
C++标准规定 main() 原型 可以有两种形式
int main();
和
int main( int argc, char *argv[] )
返回 return 可以省略,但省略后默认等于 return 0 , 而返回
return 0 一般表示程序正常结束
(2). 递归
递归就是函数体内调用自身,如累加操作。1+2+3+n (n=10)
int
Acc(
int
num)
{
if
(
num
< 0 )
{
return
0;
}
return
num
+ Acc(
num
-1);
}
....
Acc(10)
(3). 内联函数
有些函数由于函数体非常简单,我们可以采用一种优化策略既 将该函数体的代码展开“复制到”调用该函数的地方。C++将采用这种策略的函数叫内联函数。提供了关键字 inline ,当函数使用 inline 声明。
inline
int
Add(
int
x,
int
y)
{
return
x
+
y
;
}
-
<原创文章 转载请注明出处 http://blog.youkuaiyun.com/meiwm 谢谢>
出处:
http://blog.youkuaiyun.com/meiwm
本文为原创,本文版权归作者所有。欢迎转载,但请务必保留此段声明,且在文章页面明显位置给出原文连接,谢谢合作。
-