100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > c++ 函数 -函数重载 -特殊用途的语言特性(默认实参 内联函数 constexpr assert NDEBUG)

c++ 函数 -函数重载 -特殊用途的语言特性(默认实参 内联函数 constexpr assert NDEBUG)

时间:2018-12-12 20:54:57

相关推荐

c++ 函数 -函数重载 -特殊用途的语言特性(默认实参 内联函数  constexpr  assert NDEBUG)

c++ 函数 -函数重载 -特殊用途的语言特性

文章目录

c++ 函数 -函数重载 -特殊用途的语言特性函数重载定义:重载和const形参const_cast 和重载const_cast 重载和作用域 三种与函数相关的语言特性默认实参内联函数和 constexpr 函数内联函数可以避免函数调用开销字面型常量constexprconstexpr 变量constexpr 变量 意义:constexpr 变量 作用:constexpr 函数 把内联函数和constexpr 函数一般放在 头文件中 调试帮助assert 预处理宏 --定义在 cassert 头文件 中NDEBUG 预处理变量

函数重载

定义:

如果在同一个作用域内的几个函数的名字相同,但是形参列表不相同,我们称之为函数重载

重载和const形参

顶层const 不影响传入的函数的对象 ,一个拥有顶层const 的形参无法和 另一个没有顶层const 的形参

无法区分开来,故无法实现函数重载

void init(int a);void init(const int a);//这两组声明是等价的void init(int * a);void init(int * const a);//等价 声明

另一方面

如果形参是某种类型的指针或引用,则通过区分其指向的是常量对象还是非常量对象。这样就可以实现函数重载,此时的const 是底层的

void init(int& );//作用于int l类型的引用void init(const int& ); //新函数,作用于 常量应用 void init(int * a);void init(const int * a); //新函数 作用于指向常量的指针

在这个例子上:

编译器会通过实参是否是常量来判断我们该使用那个函数,因为const不能转换成其他类型,故我们只能把const对像 传递给const 实参 相反的,因为非常量可以转换成常量类型,所以非常量可以作用于上边的四个函数都可以,但是当我们传递出一个非常量对象或非常量对象的指针时,编译器会优先调用 非常量版本的重载函数。

const_cast 和重载

const_cast

const_cast 在重载函数的情境中最有用,举个例子

const string & shorterString (const string &s1,const string & s2){return s1.size() => s2.size() ? s2 : s1} //返回较短的内个引用/*该函数的参数和返回值类型都是 const string 的引用 我们可以对两个非常量的string 调用这个函数,但返回的结果仍然是const_string 的引用,因此我们需要一种新的shortString函数,当他的实参 不是常量时,得到的结果就是一个普通的引用,*/

使用const_cast 可以做到这一点

string & shorterString (string &s1,string & s2){//首先将s1和s2 的实参转换成const 的引用 然后调用 该函数的const 版本 //返回还是对const string 的引用 auto &r = shorterString (const_cast<const string &>(s1),const_cast<const string &>(s2))// auto & 这个引用 还绑定在了某个初始值的非常量的引用上(s1,s2)//最终,我们再将 其转换会一个普通的 string& ,//这样作的目的就是使得程序更加的安全return const_cast<string &>(r)}

重载和作用域

编译器 在调用一个函数的时候 ,首先实在当前作用域来寻找 所需的名字 编译器就会忽略掉外城作用域中的同名实体

在c++中 名字查找发生在类型检查前边

三种与函数相关的语言特性

默认实参

某些函数有这样的一些形参,在函数的很多次调用 中他们都被赋予了一个相同的值,此时我们把函数反复出现的值称为函数的默认实参,调用含有默认实参的函数时,,可以包含该实参,也可以省略该实参

例如:我们使用string 对象表示窗口内容 ,一般情况下,我们希望,该窗口的高,宽和背景字符都使用默认值,也能接受用户为这几个参数自由指定,和默认这几个值,

string screen(int ht = 24,int wid = 80,char backrnd = ' ');

需要注意的是:一旦某个形参被赋予了,默认值,他后面的所有形参都必须有默认值

一般函数的声明 ,只声明一次,,但多次声明一个函数也是合法·的,不过需要注意给定的作用域中, 一个形参只能被赋予一次默认实参,

意斯就是 函数后续声明只能为之前那些没有默认值的形参添加默认实参,而且该形参右侧 的所有 形参 必须都有默认值

#include<iostream>using std::cout;using std::endl;void f(int a, int b = 1){cout << a + b << endl;}int main(){f(1);void f(int a = 2, int b = 1);f();return 0;}

内联函数和 constexpr 函数

调用一个函数一般比求等价 表达式 的值要慢一些,在大多数的机器上,一次函数 调用 其实 包含 者一系列工作:调用前要 先保存寄存器 ,并在返回时恢复,可能需要拷贝参数,可能需要拷贝实参,程序转向 一个新的位置继续执行

内联函数可以避免函数调用开销

将函数指定 为 内联函数 ,通常就是 将他在每个内联点 展开 ,一般来说,内联机制用于 优化规模较小,流程直接 ,调用频繁的函数,

字面型常量

解释:(字面值类型) 常量表达式的值需要在 编译时就 得到计算 ,因此 对声明 constespr s时用到的 类型

必须有所限制,算术类型、引用 、和指针都属于 字面值类型 。像自定义类、IO库 string 类型 则不属于字面值类型

尽管 指针和引用 都能定义成 constexpr ,但他们的初始值都受到严格的控制,一个constexpr 指针的初始值必须时nullptr,

或者是 储存于某个固定 内存 的对象

constexpr

constexpr 函数 是指能 用于常量表达式 的函数 ,

/*常量表达式 是指值不会 改变 并且 不会改变 并且在编译 过程中就能得到计算结果的表达式,例如const int max_files = 20;//max_files 是常量表达式const int limit = max_files+1 //是常量表达式int a = 20; //不是const int sz = get_size(); //不是,区分的主要方法就是,看是否是在编译 过程中就能得到计算结果的表达式//除非 get_size()是一个constexpr 函数*/

constexpr 变量
constexpr 变量 意义:

在一个复杂的系统中,很难 ,分辨一个初始值到底是不是常量,当然可以定义一个 const 变量,并把他的初始值,设置为我们认为的某个常量表达式,但在实际的使用中,尽管要求如此,却常常发现 初始值并非是常量表达式,可以说,在此种情况下,对象的定义和使用完全是两回事

constexpr 变量 作用:

声明一个 constexpr 类型 以便于有编译器 来验证 变量的值是否是一个常量表达式,

声明为一个constexpr 变量 ,一定是一个常量,并且 必须用 一个常量表达式 来初始化

一般来说如果你认定一个变量是常量表达式,那就把他声明为 constexpr 变量

constexpr 函数

定义constexpr 函数的方法于一般函数类似

不过要遵循几项约定:

函数的返回值类型 以及 所有形参的类型 都得是字面值类型 而且函数 体中必须有且只有一条return 语句

#include<iostream>using std::cout;using std::endl;constexpr int new_sz(int a){return a;}int main(){constexpr int i = new_sz(1);cout << i;return 0;}

把内联函数和constexpr 函数一般放在 头文件中

和其他函数不同,内联函数和 constexpr 函数可以在函数中多次定义

毕竟 编译器 需要或者 展开 函数 仅有 函数声明 是不够的 含需要 函数的定义

但是对于 某个给定的 内联函数 或者 constexpr 函数来说 他的多个定义必须完全 一致 基于这个原因 内联函数 和constexpr 函数 通常定义在 头文件中

调试帮助

预处理器

头文件保护符

#define 指令是把一个 名字设定 为 预处理 变量#ifdef 当且仅当变量已定义为真#ifndef 当且仅当变量未定义为真#endif 一旦检查 #ifdef 或 ifndef 检查为真 则遇到 #endif 停止

c++程序员 又是会用到 一种类似 于 头文件的保护 即头文件保护 符

以便有选择地执行和调试代码

基本思想 是 ,程序 可以 包含 一些 用于 调试 地代码 但这些 代码 只能在 开发程序中使用 当应用 程序 编写完成 准备 发布时,要先屏蔽掉调试代码 这种 方法用到了 两种 预处理功能 assert 和 NEDEBUG

assert 预处理宏 --定义在 cassert 头文件 中

assert 是一种预处理宏 所谓 预处理宏 其实 就是 一个 预处理 变量 它的行为 有点类似 于 内连函数

assert(espr)

​ 首先是对 expr 求值,如果表达式为假 assert 输出信息 并终止 程序的执行 如果 表达式 为真 则 assert 神魔也不作

例如

断定接受的值都是大于 100的

int a;cin>> a;assert ( a>100);

NDEBUG 预处理变量

。。。。。。。。。。。未完待续

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。