C++函数详解

函数—C++的编程模块

目录

  • 函数基本知识
  • 函数参数和按值传递
  • 函数和数组
  • 函数和二维数组
  • 函数和C-风格字符串
  • 函数和结构
  • 函数和array对象
  • 函数指针

一、函数基本知识

1.创建函数的3方面:定义、提供原型和调用

C++对于返回值的类型有一定的限制:不能是数组,可以是其它任何类型--整数、浮点数、指针、结构和对象。(数组可以作为结构、对象组成部分来返回)

函数通过将返回值复制到指定的CPU寄存器或内存单元中将其返回。若函数包含多条返回语句(如位于不同的if else选项中),则函数在执行遇到的第一条返回语句后结束。

2.原型描述了函数到编译器的接口,它将函数返回值的类型以及参数类型和数量告诉编译器。

C++编程风格是将main( )放在最前面,它提供程序的整体结构。

3.函数原型是一条语句。(即函数定义中的函数头并添加分号)

函数原型不要求提供变量名(要有类型列表),变量名相当于占位符,因此也不必与函数定义中的变量名相同。

4.原型可降低程序出错几率,确保编译器正确处理函数返回值、检查使用的参数数目、类型是否正确。

C++中原型自动将被传递的参数强制转换为原型中指定的类型,条件是两者都是算术类型。在编译阶段进行的原型化被称为静态类型检查。

二、函数参数和按值传递

  1. 用于接收传递值的变量被称为形参,传递给函数的值被称为实参。C++标准使用参数来表示实参,使用参量来表示形参,因此参数传递将参数赋给参量。
  2. 当函数参数有多个且类型相同时,提供变量名将使原型更容易被理解。
  3. 形参与其他局部变量的主要区别:

形参从调用该函数那里获取值,而其他变量是从函数中获得值。

三、函数和数组

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-风格字符串

  1. 将字符串作为参数时传递的是字符串第一个字符的地址,这意味着字符串函数原型应将其表示字符串的形参声明为char * 类型,同时可以使用const来禁止对字符串参数进行修改。
  2. 处理字符串中字符的标准方式:

  while( * str) // *str表示第一个字符,str指向空值字符时*str为0

  {

       statements

       str++;

  }

函数无法返回一个字符串,但可以返回字符串的地址(指针)

       3.要创建包含n个字符的字符串,需要能够存储n+1个字符的空间,以便能够存储空值字符。

       4.当函数返回一个指针,且该指针指向new分配的内存时,须使用delete。

六、函数和结构

  1. 与数组不同,结构将其数据组合成单个实体或数据对象(被视为一个整数)。使用结构编程时,最直接的方式是像处理基本类型那样来处理结构,将结构作为参数传递,并在需要时将结构用作返回值使用。另外,更多人选择传递结构的地址,然后使用指针来访问结构的内容。
  2. 当cin被用于测试表达式中时,将根据输入是否成功,被转换为bool值true或false。并消除了将某些数值排除在外、终止循环的限制。因为它接受任何有效的数字输入。若程序在输入循环后还需进行输入,则必须使用cin.clear( )重置输入。
  3. 将函数形参声明为指向结构的指针,在调用函数时,将结构的地址传递给它;由于形参是指针而不是结构,因此应使用间接成员运算符(->)。

七、函数和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);

  1. 以下函数原型特征标和返回类型相同:

  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进行简化。

你可能感兴趣的:(c++,c语言)