| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> C++ Primer Plus (6th) Chap7 函数--C++的编程模块 摘录 -> 正文阅读 |
|
[C++知识库]C++ Primer Plus (6th) Chap7 函数--C++的编程模块 摘录 |
7.1 复习函数基本知识要使用C++函数,必须完成如下工作; 提供函数定义; 提供函数原型; 调用函数; 库函数使已经定义和编译好的函数,同时可以提供标准库头文件提供其原型; 执行simple()时,将暂停执行main()中的代码;等函数simple()执行完毕后,继续执行main()中的代码。 7.1.1 定义函数将函数分为有返回值和无返回值类型。没有返回值类型称为void函数。其通用格式如下:
其中parameters指定了传递给函数的参数类型和数量。 有返回值的函数将生成一个值,并将它返回给调用函数。
返回值本身可以是常量。变量,也可以是表达式,只是其结果的类型必须为typeName或可以被转化为typeName。 C++返回值的类型有一定限制:不能是数组,但可以是其他任何类型--整数、浮点数、指针,甚至可以是结构和对象!(虽然不能直接返回数组,但可以将数组作为结构或对象组成部分返回)。 函数通过将返回值复制到指定CPU寄存器或内存单元中将其返回。随后,调用程序将查看该内存单元。返回程序和调用程序必须就该内存单元中存储的数据类型达成一致。函数原型将返回值类型告知调用程序,而函数定义命令被调用函数应返回什么类型的数据。 函数在执行返回语句后结束。如果函数包含多条返回语句(例如,它们位于不同的if else选项中),则函数在执行遇到的第一条返回语句后结束。 7.1.2 函数原型及函数调用 函数原型描述了函数到编译器的接口,也就是说,它将返回值的类型(如果有的话)以及参数的类型和数量告诉编译器。因此编译器知道应该检索多少个字节以及如何解释它们。 避免使用函数原型的唯一方法,在首次使用函数之前定义它,但这不总是可行的。 函数原型是一条语句,因此必须以分号结束。获得原型最简单的方法是,复制函数中定义的函数头,并添加分号。 然而,函数原型不要求提供变量名,有类型列表就行了。 通常,在原型的参数列表中,可以包括变量名,也可以不包括。原型中的变量名相当于占位符,因此不必于函数定义中的变量名相同。 在C++中,括号为空与在括号中使用关键字void是等效的--意味着函数没有参数。 原型的功能: 编译器正确处理函数返回值; 编译器检查使用的参数数目是否正确; 编译器检查使用的参数类型是否正确;如果不正确,则转换为正确的类型; C++自动将传递的值转换为原型中指定的类型,条件是两者都是算数类型。 函数重载可能导致二义性,因此不允许某些自动强制类型转换。 自动类型转换并不能避免所有可能的错误。当较大的类型被自动转换为较小类型时,有些编译器将发出警告,指出这可能丢失数据。 仅当有意义时,原型化才会导致类型转换。例如,原型不会将整数转化为结构和指针。 在编译阶段进行的原型化被称作静态类型检查(static type checking)。可以看出,静态类型检查可捕获许多在运行阶段难以捕获的错误。 7.2 函数参数和按值传递用于接受传递值的变量被称为形参。传递给函数的值被称为实参。 C++标准使用参数(argument)来表示实参,使用参量(parameter)来表示形参。 在函数中声明的变量(包括参数)是该函数私有的。此类变量被称为局部变量,因为它们被限制在函数中。 7.2.1 多个参数在声明或者定义参数时,在函数头使用由逗号分隔的参数声明列表。 函数可以有多个参数。在调用参数时,只需使用逗号将这些参数分开。
如果两个参数的类型相同,则必须分别指定每个参数的类型。 函数原型中的变量名不必与定义的变量名相同,而且可以省略。然而,提供变量名将使原型更容易理解,尤其是两个参数的类型相同时。这样,变量名可以提醒参量与参数间的对应关系。 形参与其他局部变量的主要区别是,形参从调用函数哪里获得自己的值,而局部变量从函数内部定义获得自己的值。 7.3 函数和数组函数是处理复杂类型(如数组和结构)的关键。
方括号指出arr是一个数组,而空括号表明,可以将任何长度的数组传递给该函数。但实际情况并非如此:arr实际上并不是数组,而是一个指针。 7.3.1 函数如何使用指针来处理数组在大多数情况下,C++将数组名视为指针。该规则也有一些例外。首先,数组声明使用数组名来标记存储位置;其次,对数组名使用sizeof将得到整个数组的长度;最后,将地址运算符&用于数组名时,将返回整个数组的地址。 在C++中,当也仅当用于函数头或函数原型中,int* arr与int arr[]的含义才相同。它们都意味着arr是一个int指针。然而,数组表示法提醒用户,arr不仅指向int,还指向int数组的第一个int。当指针指向数组的第一个元素时,本书使用数组表示法;而当指针指向一个独立的值时,使用指针表示法。
7.3.2 将数组作为参数意味着声明传递常规变量时,函数将使用该变量的拷贝; 但传递数组时,函数将使用原来的数组。 将数组地址作为参数可以节省复制整个数组所需的时间和内存。 为将数组类型和元素数量告诉数组处理函数,请通过两个不同的参数来传递它们。
7.3.3 更多数组函数示例构思程序时将存储属性和操作结合起来,便是超OOP思想迈进的一大步。 为防止函数无意中修改数组的内容,可在声明形参时使用关键字const。
7.3.4 使用数组区间的函数对于处理数组的C++函数,必须将数组中的数据类型、数组的起始位置和数组中元素数量提交给它;传统的C++方法是,将指向数组起始处的指针作为一个参数,将数组长度作为第二个参数。 另一个给函数提供所需信息的方法,即指定元素区间(range),这可以通过传递两个指针来完成:一个指针标识数组的开头,另一个指针标识数组的尾部。 7.3.5 指针和const
可以将指针指向一个常量,防止使用该指针修改所指向的值。 可以将指针本身声明为常量,防止修改指针指向的地址。 C++禁止将const的地址赋给非const的指针。 7.4 函数和二维数组为编写将二维数组作为参数的函数,必须牢记,数组名被视为其地址。
7.6 函数和结构与数组名就是第一个元素的地址不同的是,结构名只是结构的名称,要获得结构的地址,必须使用取址运算符&。 将结构作为参数传递,并在需要时将结构用作返回值使用。然而,按值传递结构有一个缺点,如果结构非常大,则复制结构将增加内存要求,降低系统运行的速度。 7.6.1 传递和返回结构当结构很小时,按值传递结构最合理。 7.6.3 传递结构地址假设要传递结构的地址而不是整个结构以节省时间和空间,则需要重新编写前面的函数,使用指向结构的指针。 将传值改成传地址需要修改三个地方; ? ? ? ? 调用函数时,将结构的地址(& val)而不是结构本身传递给它。 ? ? ? ? 将形参声明维指向val的指针,即typeName*。 ? ? ? ? 由于形参是指针而不是结构,因此因使用间接成员运算符(->),而不是成员运算符(.)。 7.9 递归递归----C++函数可以自己调用自己。main()除外。 7.9.1 包含一个递归调用的递归如果递归函数调用自己,则被调用的函数也将调用自己,这将无限下去,除非代码中包含终止调用用链的内容。通常的方法将递归调用放在if语句中。
test-condition最终为false,调用链将断开。 递归调用将导致一系列有趣的事情。是要if语句为true,每个recurs()调用都将执行statement1,然后在调用recurs(),而不会执行statement2。当if语句为false时,当前调用将执行statement2.当前调用结束后,程序控制权将返回调用它的recurs(),而该recurs()将执行statement2部分,然后结束,并将控制权返回给前一个调用,以此类推。
7.9.2 包含多个递归调用的递归递归方法有时被称为分而治之策略(divide-and-conquer-strategy)。如果要求的递归层次很多,这将导致函数调用数(以及存储的变量数)翻倍,这种递归方式将是一种很糟糕的选择。
7.10 函数指针函数的地址是存储其机器语言代码的内存的开始地址。 例如,可以编写将另一个函数的地址作为参数的函数。这样第一个函数将能够找到第二个函数,并运行它。与直接调用另一个函数相比,这种方法很笨拙,但它允许在不同的时间传递不同函数的地址,这意味着可以在不同的时间使用不同的函数。 将程序员要使用的算法函数的地址传递给调用函数,必须要完成下面工作: ????????获取函数的地址; ? ? ? ? 声明一个函数指针; ? ? ? ? 使用函数指针来调用函数; 获取函数的地址很简单,只要使用函数名(后面不跟参数和函数调用符号())即可。
一定要区分传递的是函数地址还是函数的返回值。 声明指向函数的指针时,也必须指定指针指向的函数类型。这意味着声明应指定函数的返回类型以及函数的特征标(参数列表)。 通常,要声明指向特定类型的函数的指针,可以首先编写这种函数的原型,然后用(*func_p)替换函数名。这样func_p就是这类函数的指针。 为提供正确的优先级,必须在声明中使用括号*func_p括起。括号的优先级比*运算符高。
7.10.3 深入探讨函数指针
[]运算符优先级高于*运算符,因此*pf[3]表明pa是一个包含三个指针的数组。 自动类型推导只能用于单值初始化,而不能用于初始化列表。 自动类型推导存在一个潜在缺点,自动类型推导确保变量的类型与赋给它的初值的类型一致,但您提供的初值的类型可能不对。 7.10.4 使用typedef
7.11 总结函数是C++的编程模块,要使用函数,必须提供函数定义和原型,并调用函数。 函数定义是实现函数功能的代码; 函数原型描述了函数的接口:传递给函数的值的数目和种类以及函数的返回类型。 函数调用使得程序将参数传递给函数,并执行函数的代码。 在默认情况下,C++函数按值传递参数。这意味着函数定义的形参是新的变量,它们被初始化为函数调用所提供的值。以此,C++函数通过拷贝、保护了原始数据的完整性。 C++处理结构的方式与基本类型完全相同。 C++函数可以递归。函数代码中可以包括对函数本身的调用。 C++函数名和函数地址的作用相同。通过函数指针作为参数,可以传递要调用函数的名称。 |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 3:11:16- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |