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) 重载函数的确定

编译器会以下面的顺序确定要调用的函数:

  1. 精确匹配:

    • 实参的类型和形参完全相同。
    • 实参从数组类型或者函数类型转换为对应的指针类型。
    • 向实参添加顶层const或者从实参中移除顶层const
  2. 通过const转换实现的类型匹配。
  3. 通过类型提升实现的匹配。
  4. 通过算数类型转换实现的匹配。
  5. 通过类类型转换实现的匹配。

(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))

内联函数存在一些限制:

  • 不能存在循环语句
  • 不能存在过多的条件判断语句
  • 函数体不能太长
  • 不能取函数的地址
  • 内敛函数声明必须在调用这个函数之前

五、后置返回类型

C++11提供了函数的后置返回类型,用于兼容自动类型推断:

auto func() -> void {} // 等价于 void func() {}

C++ 函数详解的更多相关文章

  1. malloc 与 free函数详解<转载>

    malloc和free函数详解   本文介绍malloc和free函数的内容. 在C中,对内存的管理是相当重要.下面开始介绍这两个函数: 一.malloc()和free()的基本概念以及基本用法: 1 ...

  2. NSSearchPathForDirectoriesInDomains函数详解

    NSSearchPathForDirectoriesInDomains函数详解     #import "NSString+FilePath.h" @implementation ...

  3. JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解

    二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...

  4. Linux C popen()函数详解

    表头文件 #include<stdio.h> 定义函数 FILE * popen( const char * command,const char * type); 函数说明 popen( ...

  5. kzalloc 函数详解(转载)

    用kzalloc申请内存的时候, 效果等同于先是用 kmalloc() 申请空间 , 然后用 memset() 来初始化 ,所有申请的元素都被初始化为 0. view plain /** * kzal ...

  6. Netsuite Formula > Oracle函数列表速查(PL/SQL单行函数和组函数详解).txt

    PL/SQL单行函数和组函数详解 函数是一种有零个或多个参数并且有一个返回值的程序.在SQL中Oracle内建了一系列函数,这些函数都可被称为SQL或PL/SQL语句,函数主要分为两大类: 单行函数 ...

  7. jQuery.attr() 函数详解

    一,jQuery.attr()  函数详解: http://www.365mini.com/page/jquery-attr.htm 二,jQuery函数attr()和prop()的区别: http: ...

  8. memset函数详解

    语言中memset函数详解(2011-11-16 21:11:02)转载▼标签: 杂谈 分类: 工具相关  功 能: 将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值, 块的大 ...

  9. CreateFile函数详解

    CreateFile函数详解 CreateFile The CreateFile function creates or opens the following objects and returns ...

  10. MYSQL常用内置函数详解说明

    函数中可以将字段名当作变量来用,变量的值就是该列对应的所有值:在整理98在线字典数据时(http://zidian.98zw.com/),有这要一个需求,想从多音字duoyinzi字段值提取第一个拼音 ...

随机推荐

  1. 为什么使用kotlin可以节省开发时间

    前言:.kotlin是一门语言,光靠一篇文章要入门不太现实,所以这篇文章重点讲的是kotlin相对于java的一些特性和这些特性带来的好处. 一.简单介绍 Kotlin 是一种在 Java 虚拟机上运 ...

  2. 「洛谷P1231」教辅的组成 解题报告

    P1231 教辅的组成 题目背景 滚粗了的HansBug在收拾旧语文书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本语文书里面发现了一本答案,然而他却明明记得这书应该还包含一份练习 ...

  3. 「2018-12-02模拟赛」T2 种树 解题报告

    2.种树(tree.pas/cpp/in/out) 问题描述: Fanvree 很聪明,解决难题时他总会把问题简单化. 例如,他就整天喜欢把图转化为树.但是他不会缩环,那他怎么转化呢? 这是一个有 n ...

  4. @Configuration结合@Bean实现对象的配置

    @Configuration结合@Bean实现对象的配置 前提:最近项目中需要做支付接口,支付宝以及微信支付,本文并不介绍如何写支付接口,而是通过这个示例讲解配置应该怎么写,项目中使用的是Kotlin ...

  5. 开源API网关,你选对了么?

    开源API网关,你选对了么? api网关的本质 不用扯那么多,也不用画图,一句话说清楚 api网关:流量总入口,得以集中控制! 就这么简单 api网关协议上最基本要支持HTTP 和 WebSocket ...

  6. 【转】python get-pip.py could not find a version that satisfies

    转:https://blog.csdn.net/yanlisuo/article/details/81357305 转:https://blog.csdn.net/dyrlovewc/article/ ...

  7. spring get方法 中文(UTF-8)乱码

    问题: 前端用Get方法进行如下请求: 在浏览器中输入:http://localhost:8080/dmaList/ExportBySQL?sql=&names=分区级别&size=1 ...

  8. ArcEngine 创建要素,删除要素,生成网格,渲染图层(VB)

    示例代码:https://github.com/yu969890202/ArcEngine/tree/master/WinFrom_ArcEngine_PointDistribution博客后面有两张 ...

  9. C++Primer第五版 6.1节练习

    练习6.1:实参和形参的区别是什么? 通俗解释: 实参是形参的初始值.编译器能以任意可行的顺序对实参求值.实参的类型必须与对应的形参类型匹配. 详解1) 形参变量只有在函数被调用时才会分配内存,调用结 ...

  10. react-mockjs

    2020-01-17 react-mockjs 使用 最近参加了公司的一个新的项目,前后端同时开发,这时后端提供不了前端接口,那么就要靠咱们前端自己mock数据啦. 用到mock 数据的工具是 moc ...