频道栏目
首页 > 程序开发 > 软件开发 > C++ > 正文
C++中的函数新特性
2017-01-23 09:31:00      个评论    来源:wyfwyf12321的博客  
收藏   我要投稿

C++中的函数新特性:先来速成新特性1. 内联函数,说到内联函数,不得不提和它类似的一个东西先。

#define F(x) ((x)*(x))

没错,就是宏定义。
在程序编译过程中,F(x)会自动替换成((x)*(x))
从而在程序中F(x)就像一个函数一样

C++中当然也有宏定义
不过有一个新特性
能够得到与此类似的实现

inline int F(int x)
{
    return x*x;
}

和普通函数的定义几乎一模一样,不过就是在声明语句前面加了一个词
inline

作用:和宏定义类似,在函数调用的地方,
编译器将会使用相应的函数代码替换函数的调用
也就是在编译阶段就替换代码
实际运行的时候已经没有函数调用了
这一点是和宏定义类似的

2. 函数参数默认值

在C++的函数中,我们可以在声明的时候添加默认值

语法简介

放码过来 展示下语法
如下面
这是函数原型:

int function(int a = 2)

这是函数定义:

int function(int a)
{
    return a*a;
}

然后在调用函数的时候,我们可以这样

function(6);
//返回36
function(4);
//返回16
function();
//返回4

嗯??第三条语句并没有传递参数呀?

在没有传递参数的时候
函数会自动采用在声明时使用的默认值

3. 函数重载

C++中,是允许同名函数的存在的
在调用函数的时候,
会根据函数的形参列表选择其中一个执行
所谓函数重载便是如此

例:我们可以定义这样一组函数

void print(int a);
void print(int a,int b);
void print(double a);
void print(int a, double b);
void print(doubla a, int b);

然后我们在调用函数的时候

print (3);// 调用第一个
print (3,4); //调用第二个
print (3.0); //调用第三个
print (3,2.0); //调用第四个
print (2.0, 2); //调用第五个

这几个调用都会调用不同的函数

4. 函数模板

如果我要打一个交换两个int变量的函数
我可以这样

void swap(int & a, int & b)
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}

如果我还要打一个交换double变量的呢?
如果我还要交换long变量呢?
我是不是都要打一个swap函数!!
好烦!!
函数模板,就是为了解决你这样的烦恼而来
且看下面

template 
void swap(T & a, T & b)
{
    T temp;
    temp = a;
    a = b;
    b = temp;
}

关键字:template(模板)
关键字:typename

第一行,指出这是一个函数模板
一个可替代的变量类型,我们暂且命名为T
然后后面函数的定义
就用T来代替具体的类型
之后我们的函数调用
就可以用这一个swap函数,去交换int变量
去交换double变量

实际上函数模板就是在编译的时候
将T换成所需要的类型
就像 typedef T int ;一样

下面是一些比较细的注意事项
最好边看边打码边实践

1. 内联函数

为什么我们需要内联函数

1. 为了效率

函数的调用原理
函数调用时
需要程序在运行时跳到调用函数所在地址
然后执行函数后,跳回上一级并且返回值
在这一跳一跳的过程
需要做很多事情

宏定义和内联函数
都通过直接替换代码的做法
避免了常规的函数调用
节省了计算资源和存储空间

2. 为了避免宏定义的弊端

#define F(x) ((x)*(x))

就如同这条宏定义
为什么要加这么多括号呢?
(希望能够自己思考一下)

如果不加
当我们使用F(x+1)
宏定义会替换成 x+1 * x+1
明显不能算出我们所期待的x+1 的平方

再如,如果在含有这条宏定义的程序中
我们这样
F(c++);
又会发生什么呢?

替换后会变成
c++ * c++
结果不好确定
而且c还被加了两遍
一定不会是自己所期望自己的结果
返回c的平方后c++;

这些种种弊端,内联函数都不存在
只管当普通函数用就好啦

使用内联函数的注意事项

被调用多次且短小的程序适合作为内联函数 只被调用一两次,或者函数定义代码比较长,不适合用内联函数 !! 内联函数不能递归

2. 函数参数默认值

两个注意事项

从右向左添加默认值 默认值只加在函数原型,函数定义中不用加参数默认值
下面我解释一下上面的两句话

1. 从右向左添加默认值

假设有这样的一个函数原型
int function (int a, int b = 3, int c )
我这样调用
function(2,4);
这是想做什么呢?
是因为b有了默认值,想只给a和c赋值吗?
但是

实参按从左向右的顺序依次赋给对应的形参
也就是说
2 会赋给 a , 4 会赋给 b,
不会跳过默认值

不过,我们可以这样修改函数原型
int function (int a, int c , int b = 3)
这样就没有问题了

所以,默认值从右往左添加

2. 只有函数原型需要加默认值

这个注意事项相信大家再看会该节开头的例子就懂了
这是函数原型:

int function(int a = 2)

这是函数定义:

int function(int a)
{
    return a*a;
}

3. 函数重载

函数特征标

先明白一个概念:函数的特征标

函数特征标
对于相同名字的函数
函数的特征标由函数定义的形参列表决定
例:
int function (int , int );
int function (double );
第一个函数的形参列表为(int, int)
第二个函数的形参列表为(double)
所以虽然相同名字,这是两个不同的函数

成功重载的条件

const可以重载吗

void print(int a);
void print (const int a);

这个是不可以的,

void print (int & a);
void print (const int & a);

这个是可以的

void print (int * a);
void print (const int * a);

这个也是可以的

我其实很想解释解释为什么可以为什么不可以的
然后发现我不会解释
不过在DEV上亲测过

引用变量能重载吗

void print (int a);
void print (int & a);

这两个是无法重载的

二义性与类型转换

假设这里定义了这样的函数
void print (int a, double = 3);
void print (int b);
这两个当然是不同的函数,当然可以重载
可是,如果我这样调用函数
print(3);
对于第一个版本,当然可以使用,因为第二个参数默认为3,可以省略
对于第二个版本,毫无疑问可以使用
这下子怎么办????
编译器就会报错
这就叫做具有二义性

二义性是指
访问同名成员的不确定性
包括访问函数,访问类成员。。。

在类型转换中,同样可能会有二义性
例子:这里定义了这几个函数

void print (int a);
void print (double a);

然后

unsigned int u = 3;
print(u);

会发生什么?

这里没有一个函数与u匹配,
因此u会尝试类型转换从而匹配
u既可以转为int类型也可以转为double类型
出现二义性
编译器无法确定
报错

函数模板

明天再细写函数模板吧
真是一个大坑

点击复制链接 与好友分享!回本站首页
上一篇:c++设计模式之访客模式
下一篇:C++ 获取文件下的所有文件的名字
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站