函数—C++的编程模块
目录
一、函数基本知识
1.创建函数的3方面:定义、提供原型和调用
C++对于返回值的类型有一定的限制:不能是数组,可以是其它任何类型--整数、浮点数、指针、结构和对象。(数组可以作为结构、对象组成部分来返回)
函数通过将返回值复制到指定的CPU寄存器或内存单元中将其返回。若函数包含多条返回语句(如位于不同的if else选项中),则函数在执行遇到的第一条返回语句后结束。
2.原型描述了函数到编译器的接口,它将函数返回值的类型以及参数类型和数量告诉编译器。
C++编程风格是将main( )放在最前面,它提供程序的整体结构。
3.函数原型是一条语句。(即函数定义中的函数头并添加分号)
函数原型不要求提供变量名(要有类型列表),变量名相当于占位符,因此也不必与函数定义中的变量名相同。
4.原型可降低程序出错几率,确保编译器正确处理函数返回值、检查使用的参数数目、类型是否正确。
C++中原型自动将被传递的参数强制转换为原型中指定的类型,条件是两者都是算术类型。在编译阶段进行的原型化被称为静态类型检查。
二、函数参数和按值传递
形参从调用该函数那里获取值,而其他变量是从函数中获得值。
三、函数和数组
1.在C++中,当(且仅当)用于函数头或函数原型中,int * arr和int arr[ ] 的含义才相同,都意味着arr是一个int指针。
arr[i] = = *(arr+i) //两种记法等价(值)
&arr[i] = = arr+i //两种记法相同(地址)
将指针(包括数组名)加1,实际上是加上了一个与指针指向的类型的长度(以字节为单位)相等的值。对于遍历数组而言,使用指针加法和数组下标等效。
2.要使用两个不同的参数来传递数组类型和元素个数给函数:
void fillArray(int arr [ ], int size);
编写特定的函数来处理特定的数据操作能使程序的可靠性更高、修改和调试更方便。
3.由于接受数组名参数的函数访问的是原始数组,因此可通过调用该函数将值赋给数组元素。为防止函数无意中修改数组的内容,可在声明形参时使用关键字const:
void show_arr(const double arr[ ], int n); //即不能在show_arr中使用arr修改其数据。
4.使用数组区间的函数
a. 将指向数组起始处的指针作为一个参数,将数组长度作为第二个参数(指针指出数组的位置和数据类型)
b. 指定元素区间:一个指针标识数组开头,另一个指针标识数组结尾。对于数组而言,标识数组结尾的参数是指向最后一个元素后面的指针。
5.指针和const
a. 指针指向一个常量对象,可防止使用该指针来修改所指向的
b. 将指针本身声明为常量,可防止改变指针指向的位置。这样可避免由于无意间修改数据而导致的编程错误;使用const使得函数能够处理const和非const实参,否则将只能接受非const数据。如:
int g = 16;
int c = 12;
const int *pt = &g;
*pt = 20; //NO,禁止修改pt指向的值
pt = &c; //OK,pt可以指向另一个变量
int *const pt = &g;
*pt = 20; //OK, pt可以用来修改值
pt = &c; //NO,禁止改变pt指向的变量
可将const变量的地址赋给指向const的指针:
const float x = 9.80;
const float *pe = &x;
C++禁止将const的地址赋给非const指针,当且仅当只有一层间接关系(如指针指向基本数据类型)时,才可将非const地址或指针赋给const指针。
四、函数和二维数组
牢记,数组名被视为地址,即相应的形参是一个指针。原型中函数参数不能是数组。
五、函数和C-风格字符串
while( * str) // *str表示第一个字符,str指向空值字符时*str为0
{
statements
str++;
}
函数无法返回一个字符串,但可以返回字符串的地址(指针)
3.要创建包含n个字符的字符串,需要能够存储n+1个字符的空间,以便能够存储空值字符。
4.当函数返回一个指针,且该指针指向new分配的内存时,须使用delete。
六、函数和结构
七、函数和string对象
可以将一个结构赋给另一个结构,也可将一个对象赋给另一个对象。可将结构作为完整的实体传递给函数,也可将对象作为完整实体进行传递。
若需要多个字符串,可声明一个string对象数组,而不是二维char数组。
八、函数与array对象
在C++中,类对象是基于结构的,因此结构编程方面的有些考虑因素也适用于类,如,可按值传递将对象传递给函数,在此情况下,函数处理的是原始对象的副本;若函数要修改对象,则需要将该对象的地址传递给函数。
模板类array并非只能存储基本数据类型,它还可存储对象。
九、函数指针
1.函数的地址是存储其机器语言代码的内存的开始地址。可以编写将另一个函数的地址作为参数的函数,它允许在不同的时间传递不同函数的地址。即可以在不同的时间使用不同的函数。
2. 步骤:获取函数地址;声明一个函数指针;使用函数指针来调用函数。
a.获取函数地址:使用函数名(后面不跟参数)
process(think); //传递think( )函数的地址
process(think( )); //传递函数的返回值
b.声明函数指针
声明指向某种数据类型的指针时,必须指定指针指向的类型。即声明应指定函数的返回类型以及函数的特征标(参数列表),也就是像函数原型那样指出有关函数的信息。
ps:要声明指向待定类型的函数的指针,可先编写这种函数的原型,然后用(*pf)替换函数名,这样pf就是这类函数的指针。
3.使用指针来调用函数:把(*pf)看作函数名使用
double pam(int);
double (*pf)(int);
pf = pam;
double y = (*pf)(5); //也可为double y = pf(5);
const double *f1 (const double ar[ ], int n);
const double *f2 (const double [ ], int n);
const double *f3 (const double * , int n);
在函数原型中可以省略标识符,可在声明指针的时候初始化:
const double *(*p1) (const double * ,int ) = f1;
4.为查看存储在地址处的实际值,需将运算符*应用于这些地址。运算符[ ]优先级高于* ,因此 *pa[3]表明pa是一个包含三个指针的数组。
注意:自动类型推断只能用于单值初始化,而不能应用于初始化列表;可使用typedef进行简化。