【C++学习笔记】五、C++中的函数定义、声明、调用及实参形参等变量

1.函数的定义

参考博客:http://www.runoob.com/cplusplus/cpp-functions.html

(1)函数的分类

a. 系统函数(库函数):库函数是由头文件声明的,用户不需要自己声明,因此程序开头需要用#include指令所包含头文件

b. 用户自己定义的函数:

    i. 无参函数:无参数的函数;

    ii. 有参函数:有参数的函数。

(2)函数的定义:

一般定义形式:

return_type function_name( parameter list )
{
   body of the function
}

在 C++ 中,函数由一个函数头和一个函数主体组成。下面列出一个函数的所有组成部分:

  • 返回类型:一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值,在这种情况下,return_type 是关键字 void
  • 函数名称:这是函数的实际名称。函数名和参数列表一起构成了函数签名。
  • 参数:参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数。
  • 函数主体:函数主体包含一组定义函数执行任务的语句。

a. 无参函数:

类型名 函数名([viod])

{声明部分

执行语句}

在定义无参函数时,函数首部括号里的void可以不写

b. 有参函数:

类型名 函数名(形式参数列表)

{声明部分

执行语句}

实例如下:

// 函数返回两个数中较大的那个数
 
int max(int num1, int num2) 
{
   // 局部变量声明
   int result;
 
   if (num1 > num2)
      result = num1;
   else
      result = num2;
 
   return result; 
}

2. 函数的声明

函数的声明中,所有的类型名都不可以省略

函数声明会告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。

函数声明包括以下几个部分:

return_type function_name( parameter list );

针对上面定义的函数 max(),以下是函数声明:

int max(int num1, int num2);

在函数声明中,参数的名称并不重要,只有参数的类型是必需的,因此下面也是有效的声明:

int max(int, int);

3. 函数的调用

函数调用时所有类型名都不用写出

一般形式为:

函数名(实参列表)

函数调用有以下几个方式:

(1) 函数语句:

将函数的调用作为一个单独的语句,并不要求返回值,只是完成一定的操作,如:

printstar();

(2)函数表达式:

函数出现在一个表达式中,要求函数以一个确定的值参加表达式的运算,如:

c = 2*max(a,b)

(3)函数参数:

函数作为另一个函数的实参,即该函数的参数本身也是个函数,如:

m = max(a,sqrt(b));

函数调用中需要注意的几个特殊的问题:

a.函数的嵌套调用:

C++不允许对函数做嵌套调用,也就是说在一个函数中不能完整的包含另一个函数,每个函数都是相互平行的关系。

b.函数的递归调用:

在调用一个函数的过程中,又出现直接或间接地调用该函数本身的,称为递归调用,递归应该是有限次数、有终止的,通常以if等语句做限制。

c. 内置函数:

直观地说是函数首部最左侧带有inline的函数,作用是编译的时候就把函数插入main函数中,以节约运行时间,适合规模小而使用频繁的函数,一般不用,具体解释可参见博客:https://blog.csdn.net/chaipp0607/article/details/54934185?utm_source=blogxgwz6

d. 函数的重载:

C++ 允许在同一作用域中的某个函数运算符指定多个定义,分别称为函数重载运算符重载

具体可参见:http://www.runoob.com/cplusplus/cpp-overloading.html

e.模板函数

具体解释请参见:https://blog.csdn.net/lezardfu/article/details/56852043

4. 函数中的参数和返回值

(1)形式参数和实际参数

形式参数:在函数定义时,函数名后边括号里的参数称为形式参数;

实际参数:在函数调用时,函数名后边括号里的参数称为实际参数。

关于实参和形参的说明:

a. 在定义函数时指定的形参,在未调用时不占据存储单元,因此称为形式参数或者虚拟参数,表示并不是实际存在的数据,只有在发生函数的调用时,形参才会被分配内存单元,来接收实参传来的数据,调用结束后内存单元也被释放;

b. 实参可以是常量、变量或者表达式;(即函数调用的几种形式)

c. 定义函数时,必须在函数首部指定形参类型;

d. 实参与形参的类型应该相同或者兼容;

e. 实参对形参的数据传递是值传递,即单向传递,只由实参传给形参,而不能由形参传给实参。调用结束后,形参但愿会被释放,实参但愿仍保留原始值,因此在执行一个被调用函数时,形参的值改变不会影响实参的值。

(2)函数的返回值

返回值:通过函数的调用能使主函数得到一个确定的数值,称为返回值。

说明:

a. 函数的返回值通过return语句获得,return后加不加括号均可,函数中可以有多个return,执行到哪个,哪个起作用,若不需要返回值时,可以不要return;

b. 定义函数时,指定了返回值的类型,如果返回值与函数定义的类型不一致,则以函数的类型为准。

5. 局部变量和全局变量

(1)局部变量:

在函数内部定义的变量是内部变量,它只在本函数的范围内有效,说明如下:

a. 主函数中定义的变量(m,n)也只在主函数中有效,在其他函数中无效,主函数中也不能使用其他函数的变量;

b. 不同函数中可以使用同名的变量,代表不同的对象,互不干扰;它们会在不同的时间段占据不同的内存单元;

c. 可以在函数内的复合语句中定义变量,它们只在本复合语句中有效;

d. 形参也是局部变量,只在该函数中有效;

e. 函数声明中出现的参数名,只在声明的该语句有效。 

(2)全局变量:

全局变量是在函数之外定义的变量,说明如下:

a. 设全局变量的作用是增加了函数间的数据联系;

b. 不必要时不用全局变量,因为它在执行过程中一直占据内存单元,且使函数通用性降低;

c. 若在同一个源文件内,全局变量与局部变量同名,则在局部变量的范围内,全局变量被屏蔽,此时可以使用局部变量。

6.变量的存储类别

主要引用自:http://www.runoob.com/cplusplus/cpp-storage-classes.html

c++中的存储类主要有四种:自动的(auto)、静态的(static)、寄存器的(register)和外部的(extern)

(1)auto 存储类

自 C++ 11 以来,auto 关键字用于两种情况:声明变量时根据初始化表达式自动推断该变量的类型、声明函数时函数返回值的占位符。

C++98标准中auto关键字用于自动变量的声明,但由于使用极少且多余,在C++11中已删除这一用法。

根据初始化表达式自动推断被声明的变量的类型,如:

auto f=3.14;      //double
auto s("hello");  //const char*
auto z = new auto(9); // int*
auto x1 = 5, x2 = 5.0, x3='r';//错误,必须是初始化为同一类型

(2)static 存储类

static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值。

static 修饰符也可以应用于全局变量。当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内。

在 C++ 中,当 static 用在类数据成员上时,会导致仅有一个该成员的副本被类的所有对象共享。

ststic变量在下一次被调用时,改变量保留着其上次被调用结束时的值。

#include <iostream>
 
// 函数声明 
void func(void);
 
static int count = 10; /* 全局变量 */
 
int main()
{
    while(count--)
    {
       func();
    }
    return 0;
}
// 函数定义
void func( void )
{
    static int i = 5; // 局部静态变量
    i++;
    std::cout << "变量 i 为 " << i ;
    std::cout << " , 变量 count 为 " << count << std::endl;
}

产生如下结果:

变量 i 为 6 , 变量 count 为 9
变量 i 为 7 , 变量 count 为 8
变量 i 为 8 , 变量 count 为 7
变量 i 为 9 , 变量 count 为 6
变量 i 为 10 , 变量 count 为 5
变量 i 为 11 , 变量 count 为 4
变量 i 为 12 , 变量 count 为 3
变量 i 为 13 , 变量 count 为 2
变量 i 为 14 , 变量 count 为 1
变量 i 为 15 , 变量 count 为 0

(3)register 存储类

register 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个词),且不能对它应用一元的 '&' 运算符(因为它没有内存位置)。

{
   register int  miles;
}

该类型的变量对编译系统只是建议性的,而不是强制性的,现在优化的编译器可以自动识别频繁的变量把它们放入寄存器,不用刻意指定。

(4)extern 存储类

extern 存储类用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。当您使用 'extern' 时,对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置。

当您有多个文件且定义了一个可以在其他文件中使用的全局变量或函数时,可以在其他文件中使用 extern 来得到已定义的变量或函数的引用。可以这么理解,extern 是用来在另一个文件中声明一个全局变量或函数。

extern 修饰符通常用于当有两个或多个文件共享相同的全局变量或函数的时候,如下所示:

第一个文件:main.cpp

#include <iostream>
 
int count ;
extern void write_extern();
 
int main()
{
   count = 5;
   write_extern();
}

第二个文件:support.cpp

#include <iostream>
 
extern int count;
 
void write_extern(void)
{
   std::cout << "Count is " << count << std::endl;
}

在这里,第二个文件中的 extern 关键字用于声明已经在第一个文件 main.cpp 中定义的 count。现在 ,编译这两个文件,如下所示:

$ g++ main.cpp support.cpp -o write

这会产生 write 可执行程序,尝试执行 write,它会产生下列结果:

$ ./write
Count is 5

猜你喜欢

转载自blog.csdn.net/zl3090/article/details/84751727