C++ 函数详解
C++函数完全兼容C函数定义的风格,但是也做出了一些改进。一方面,C++函数允许使用缺省参数值和占位参数;另一方面,C++提供了重要的函数重载机制;另外,为了解决C中臭名昭著的宏缺陷问题,C++提供了内联函数的机制(C99之后也支持这个特性)。从C++11开始,函数定义支持后置返回类型。
一、缺省参数值
C++中可以在函数声明时为参数提供一个默认值,当函数调用时如果不提供实参,就使用这个默认值:
int func(int x = 0);
int main(int argc, char *argv[])
{
printf("func() = %d\n", func());
return 0;
}
int func(int x)
{
return x;
}
注意:默认值只在函数声明时有效,虽然函数定义中也可以写默认值,但是会被函数声明中的默认值覆盖。
函数默认参数的规则是:
- 参数的默认值需要从右向左提供
- 函数调用时如果使用了默认值,那么后续的参数都必须使用默认值
二、函数的占位参数
在C++中可以为函数提供占位参数。占位参数只有参数类型声明,但是没有参数名;这样,在函数的实现中是无法使用这个参数的:
int func(int)
{
return 0;
}
int main(int argc, char *argv[])
{
func(1); // 虽然参数无意义,但是还是要提供来通过编译。
return 0;
}
占位参数存在的意义是:兼容C语言中可能出现的不规范的写法,也可以配合默认值来一起使用。
三、函数重载
如果同一个作用域内的几个函数名称相同,但是参数列表不同,那它们就是重载函数:
void print(const char *cp);
void print(const int *begin, const int *end);
void print(const int ia[], size_t size);
函数重载有以下几个注意点:
(3.1) 函数重载必须至少要满足的条件
- 参数个数不同
- 参数类型不同
- 参数顺序不同
注意:返回值类型不同不能作为重载的条件。
(3.2) const与重载
如果函数以值传递参数,那么const不能构成重载:
void func(int arg);
void func(const int arg); // 错误:对func的重定义
但是,如果以指针或者引用来传递参数,那么const就可以构成重载了:
void func1(int *arg);
void func1(const int *arg); // 正确:声明了新函数
void func1(const int *const arg); // 正确:声明了新函数
void func2(int &arg);
void func2(const int &arg); // 正确:声明了新函数
另一方面,const成员函数和非const成员函数同样可以构成函数重载:
class object
{
public:
int func();
const int func() const; // 正确:声明了新函数
};
(3.3) 重载函数的确定
编译器会以下面的顺序确定要调用的函数:
- 精确匹配:
- 实参的类型和形参完全相同。
- 实参从数组类型或者函数类型转换为对应的指针类型。
- 向实参添加
顶层const或者从实参中移除顶层const
- 通过
const转换实现的类型匹配。 - 通过类型提升实现的匹配。
- 通过算数类型转换实现的匹配。
- 通过类类型转换实现的匹配。
(3.4) 重载与函数指针
由于编译器需要根据重载规则去挑选与函数指针参数列表一致的函数,并且要严格地匹配函数类型与函数指针的类型,因此无法直接通过函数名得到重载函数的入口地址:
void func(int);
void func(double);
int main(int argc, char *argv[])
{
void * v = func // 错误:无法通过函数名得到函数的地址。
void(*pFunc1)(int) = func; // 正确:获得了void func(int)的入口地址。
void(*pFunc2)(double) = func; // 正确:获得了void func(double)的入口地址。
return 0;
}
(3.5) 让编译器以C语言方式编译函数
为了兼容旧有的C语言代码库,必须以C语言的编译规则来编译函数,因此需要使用如下的方式:
- 以
__cplusplus宏来检查是否使用了C++ - 以
extern "C"来让编译器以C语言方式编译函数
#ifdef __cplusplus
extern "C" {
#endif
void func(); // 这个函数将以C语言的方式编译。
#ifdef __cplusplus
}
#endif
四、内联函数
C++中推荐以内联函数来代替宏代码片段。C++同样以直接替换代码块的方式来处理内联函数,同时没有著名的宏缺陷问题。可以使用inline关键字来请求编译器将函数以内联函数的方式处理 (编译器可能忽略这个请求):
inline void func() {...}
注意:
内联函数声明时
inline必须和函数定义结合在一起,否则编译器会忽略该请求。现代的编译器会进行优化,一些函数即使没有
inline,也可能会被内联编译。一些编译器提供了一些扩展语法,可以对函数进行强制的内联操作:
- VC:
__forceinline - g++:
__attribute__((always_inline))
- VC:
内联函数存在一些限制:
- 不能存在循环语句
- 不能存在过多的条件判断语句
- 函数体不能太长
- 不能取函数的地址
- 内敛函数声明必须在调用这个函数之前
五、后置返回类型
C++11提供了函数的后置返回类型,用于兼容自动类型推断:
auto func() -> void {} // 等价于 void func() {}
C++ 函数详解的更多相关文章
- malloc 与 free函数详解<转载>
malloc和free函数详解 本文介绍malloc和free函数的内容. 在C中,对内存的管理是相当重要.下面开始介绍这两个函数: 一.malloc()和free()的基本概念以及基本用法: 1 ...
- NSSearchPathForDirectoriesInDomains函数详解
NSSearchPathForDirectoriesInDomains函数详解 #import "NSString+FilePath.h" @implementation ...
- JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解
二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...
- Linux C popen()函数详解
表头文件 #include<stdio.h> 定义函数 FILE * popen( const char * command,const char * type); 函数说明 popen( ...
- kzalloc 函数详解(转载)
用kzalloc申请内存的时候, 效果等同于先是用 kmalloc() 申请空间 , 然后用 memset() 来初始化 ,所有申请的元素都被初始化为 0. view plain /** * kzal ...
- Netsuite Formula > Oracle函数列表速查(PL/SQL单行函数和组函数详解).txt
PL/SQL单行函数和组函数详解 函数是一种有零个或多个参数并且有一个返回值的程序.在SQL中Oracle内建了一系列函数,这些函数都可被称为SQL或PL/SQL语句,函数主要分为两大类: 单行函数 ...
- jQuery.attr() 函数详解
一,jQuery.attr() 函数详解: http://www.365mini.com/page/jquery-attr.htm 二,jQuery函数attr()和prop()的区别: http: ...
- memset函数详解
语言中memset函数详解(2011-11-16 21:11:02)转载▼标签: 杂谈 分类: 工具相关 功 能: 将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值, 块的大 ...
- CreateFile函数详解
CreateFile函数详解 CreateFile The CreateFile function creates or opens the following objects and returns ...
- MYSQL常用内置函数详解说明
函数中可以将字段名当作变量来用,变量的值就是该列对应的所有值:在整理98在线字典数据时(http://zidian.98zw.com/),有这要一个需求,想从多音字duoyinzi字段值提取第一个拼音 ...
随机推荐
- [工具] Git版本管理(知识总结)
对以下文档进行了简要总结,方面复习: [工具] Git版本管理(一)(基本操作) [工具] Git版本管理(二)(分支) [工具] Git版本管理(三)(工作流) [工具] Git版本管理(四)(贡献 ...
- 基础之Lamada和Stream的邂逅
show me the code and take to me,做的出来更要说的明白 GitHub项目JavaHouse同步收录 喜欢就点个赞呗! 你的支持是我分享的动力! 引入 是否有遇到看不懂身边 ...
- 洛谷$P3645\ [APIO2015]$雅加达的摩天楼 最短路
正解:最短路 解题报告: 传送门$QwQ$ 考虑暴力连边,发现最多有$n^2$条边.于是考虑分块 对于长度$p_i$小于等于$\sqrt(n)$的边,建立子图$d=p_i$.说下关于子图$d$的定义? ...
- [gitHub实践] 实践记录
[gitHub实践] 实践记录 版权2019.4.19更新 Q1:本地仓库和远程仓库连接提示输入用户名密码 本地仓库和远程仓库连接有两种方式 本地初始化建立一个仓库,远程也建立了一个仓库 本地建立仓库 ...
- 「洛谷P3931」 SAC E#1 - 一道难题 Tree
P3931 SAC E#1 - 一道难题 Tree 题目背景 冴月麟和魏潇承是好朋友. 题目描述 冴月麟为了守护幻想乡,而制造了幻想乡的倒影,将真实的幻想乡封印了.任何人都无法进入真实的幻想乡了,但是 ...
- C++ | C++ 基础知识 | 类型与声明
一.类型 C++ 包含一整套基本类型,这些类型对应计算机最基本的存储单元并且展现 1.0 布尔值 一个布尔变量(bool)的取值或者是 true 或者是 false,布尔变量常用于表达逻辑运算结果. ...
- Tomcat的性能优化及JVM内存工作原理
JVM性能优化原则:代码运算性能.内存回收.应用配置(影响Java程序主要原因是垃圾回收机制)代码层优化:避免过多循环嵌套.调用和复杂逻辑. Tomcat调优主要内容 1.增加最大连接数 2.调整工作 ...
- Java set接口之HashSet集合原理讲解
Set接口 java.util.set接口继承自Collection接口,它与Collection接口中的方法基本一致, 并没有对 Collection接口进行功能上的扩充,只是比collection ...
- 性能测试-详细的 TPS 调优笔记
概述 在本地针对项目的登录接口做了一次简单的压力测试.200并发持续120s,观察吞吐量 运行结束之后,吞吐量是这样的 如图所示,吞吐量波动巨大,完全不正常.现在我们需要去观察一下服务器了 mpsta ...
- Java知识体系框架
前言:自从出生,每个人都是一个学习者或探索者.永远保持一颗谦逊的心态,遵循一定的方法和规范,去学习和实践,永远记得走走停停,多回头看看自己走过的路,温故而知新,也能更好地指导未来的路怎么走(同样,本篇 ...