参考文献

注册

 

发新话题 回复该主题

CPrimerPlus学习笔记之函数 [复制链接]

1#

前言

个人觉得学习编程最有效的方法是阅读专业的书籍,通过阅读专业书籍可以构建更加系统化的知识体系。一直以来都很想深入学习一下C++,将其作为自己的主力开发语言。现在为了完成自己这一直以来的心愿,准备认真学习《C++PrimerPlus》。为了提高学习效率,在学习的过程中将通过发布学习笔记的方式,持续记录自己学习C++的过程。

一、复习函数的基本知识

要使用C++函数,必须完成如下工作:

提供函数定义;

提供函数原型;

调用函数。

1、定义函数

可以将函数分成两类:没有返回值的函数和有返回值的函数。

没有返回值的函数被称为void函数,其通用格式如下:

voidfunctionName(parameterList){statement(s)return;//可选}

其中,parameterList指定了传递给函数的参数类型和数量。

有返回值的函数将生成一个值,并将它返回给调用函数。通用格式如下:

typeNamefunctionName(parameterList){statementsreturnvalue;}

函数在执行返回语句后结束。如果函数包含多条返回语句(例如,它们位于不同的还ifelse选项中),则函数在执行遇到的第一条返回语句后结束。

2、函数原型和函数调用

原型描述了函数到编译器的接口、也就是说,它将函数返回值的类型(如果有的话)以及参数的类型和数量告诉编译器。

函数原型是一条语句,因此必须以分号结束。获得原型最简单的方法是,复制函数定义中的函数头,并添加分号。函数原型不要求提供变最名,有类型列表就足够了。

在C++中,括号为空与在括号中使用关键字void是等效的——意味着函数没有参数。

具体来说,原型确保以下几点:

编译器正确处理函数返回值;

编译器检查使用的参数数目是否正确;

编译器检查使用的参数类型是否正确;如果不正确,则转换为正确的类型(如果可能的话)

二、函数参数和按值传递

C++标准使用参数(argument)来表示实参,使用参量(parameter)来表示形参,因此参数传递将参数赋值给参量。

在函数中声明的变量(包括参数)是该函数私有的。在函数被调用时,计算机将为这些变量分配内存;在函数结束时,计算机将释放这些变量使用的内存(有些C++文献将分配和释放内存称为创建和毁坏变量)。这样的变量被称为局部变量,因为它们被限制在函数中。前面提到过,这样做有助于确保数据的完整性,这还意味着。如果在main()中声明了一个名为x的变量,同时在另一个函数中也声明了一个名为x的变量,则它们将是两个完全不同的、毫无关系的变量。这样的变量也被称为自动变量,因为它们是在程序执行过程中自动被分配和释放的。

函数可以有多个参数。在调用函数时,只需使用逗号将这些参数分开即可。

如果函数的两个参数的类型相同,则必须分别指定每个参数的类型,而不能像声明常规变量那样组合在一起。

三、函数和数组

在大多数情况下,C+和C语言一样,也将数组名视为指针。

在C++中,当且仅当用于函数头或函数原型中,int*arr和intarr[]的含义才是相同的。它们都意味着arr是一个int指针。然而,数组表示法(intarr[])提醒用户,arr不仅指向int,还指向int数组的第一个int。当指针指向数组的第一个元素时,本书使用数组表示法;而当指针指向一个独立的值时,使用指针表示法。别忘了,在其他的上下文中,int*arr和intarr[]的含义并不相同。

不能使用sizeof来获悉原始数组的长度,而必须依赖于传入正确的元素数。

为防止函数无意中修改数组的内容,可在声明形参时使用关键字const。

可以用两种不同方式将const关键字用于指针。第一种方法是让指针指向一个常量对象,这样可以防止使用该指针来修改所指向的值,第二种方法是将指针本身声明为常量,这样可以防止改变指针指向的位置。

声明一个指向常量的指针pt:

intage=39;constint*pt=age;

该声明指出,pt指向一个constint(这里为39),因此不能使用pt来修改这个值。换句话来说,*pt的值为const,不能被修改。这意味着pt的声明并不意味着它指向的值实际上就是一个常量,而只是意味着对pt而言,这个值是常量。

将const变量的地址赋给指向const的指针:

constfloatg_earth=9.80;constfloat*pe=g_earth;

五、函数和C风格字符串

假设要将字符串作为参数传递给函数,则表示字符串的方式有3种:

char数组;

用引号括起的字符串常量(也称字符串字面值);

被设置为字符串的地址的char指针。

可以说是将字符串作为参数来传递,但实际传递的是字符串第一个字符的地址。这意味着字符串函数原型应将其表示字符串的形参声明为char*类型

以下代码演示了处理字符串中字符的标准方式:

while(*str){statementsstr++;}

六、函数和结构

在涉及函数时,结构变量的行为更接近于基本的单值变量。可以按值传递结构,就像普通变量那样。函数可以返回结构。与数组名就是数组第一个元素的地址不同的是,结构名只是结构的名称,要获得结构的地址,必须使用地址运算符。

使用结构编程时,最直接的方式是像处理基本类型那样来处理结构;也就是说,将结构作为参数传递,并在需要时将结构用作返回值使用。然而,按值传递结构有一个缺点。如果结构非常大,则复制结构将增加内存要求,降低系统运行的速度。出于这些原因(同时由于最初C语言不允许按值传递结构),许多C程序员倾向于传递结构的地址,然后使用指针来访问结构的内容。C++提供了第三种选择按引用传递。

七、函数和string对象

虽然C风格字符串和string对象的用途几乎相同,但与数组相比,string对象与结构更相似。例如,可以将一个结构赋给另一个结构,也可以将一个对象赋给另一个对象。可以将结构作为完整的实体传递给函数,也可以将对象作为完整的实体进行传递。如果需要多个字符串,可以声明一个string对象数组,而不是二维char数组。

使用string对象需要包含string头文件。

如果需要string数组,只需使用通常的数组声明格式即可:

stringlist[SIZE];

可以像下面这样使用它:

getline(cin,list);

八、函数与array对象

在C++中,类对象是基于结构的,因此结构编程方面的有些考虑因素也适用于类。

使用C++11模板类array的例子。

假设您要使用一个array对象来存储一年四个季度的开支:

std::arraydouble,4expenses;

本书前面说过,要使用array类,需要包含头文件array,而名称array位于名称空间std中。如果想用函数来显示expenses的内容,可按值传递expenses:

show(expenses);

但如果函数要修改对象expenses,则需将该对象的地址传递给函数:

fill(expenses);

九、递归

C++函数除main()函数不能自己调用自己,其余函数可以自己调用自己,这种功能被称为递归。

十、函数指针

与数据项相似,函数也有地址。函数的地址是存储其机器语言代码的内存的开始地址。

要将函数地址传递给第一个函数,需要完成下面的工作:

获取函数的地址(只要使用函数名,后面不跟参数即可);

声明一个函数指针;

使用函数指针来调用函数。

当我们需要一个返回类型为double同时有一个int类型参数的函数作为参数时,需要进行如下声明:

voidMyCalcSquare(double(*pf)(int));

使用函数指针示例代码如下:

voidMyCalcSquare(intnum,double(*pf)(int));intmain(){usingnamespacestd;intcode=1;coutMyCalcSquare(code,DealInt)endl;}doubleDealInt(intnum){return0.03*lns;}voidMyCalcSquare(intnum,double(*pf)(int)){return(*pf)(num*num);}

auto关键字用于自动类型推断:

autopc=pa;

自动类型推断只能用于单值初始化,而不能用于初始化列表。

除auto外,C++还提供了其他简化声明的工具。

typeofdoublereal;

分享 转发
TOP
发新话题 回复该主题