零基础学C++之基础篇四

函数

程序是由函数组成的,一个函数就是程序中的一个模块。函数既可以互相调用,也可以将互相联系密切的语句放在一个函数内,还可以将复杂的函数分解成多个子函数。

函数概述

函数就是可以完成某个功能的代码块,函数根据功能可以分为字符函数、日期函数、数学函数、图形函数、内存函数等。

函数的定义

函数定义的一般形式如下:

类型标识符 函数名(形式参数列表)
{
	变量声明
	语句
}

类型标识符:用来标识函数的返回值类型,可以根据函数的返回值判断函数的执行情况,通过返回值也可以获取想要的数据。类型标识符可以是整型、字符型、指针型、对象的数据类型。
形式参数列表:由各种类型变量组成的列表,各参数之间用逗号间隔,在进行函数调用时吗,主调函数对变量进行赋值。

函数的声明

调用一个函数前必须先声明函数的返回类型和参数类型,如:

int SetIndex(int i);

函数声明被称为函数原型,函数声明时可以省略变量名,如:

int SetIndex(int );

实例01 函数的定义及使用

#include <iostream>
using namespace std;
void ShowMessage();
void ShowAge();
void ShowIndex();
void main()
{
	ShowMessage();
	ShowAge();
	ShowIndex();
}
void ShowMessage()
{
	cout << "Hello world." << endl;
}
void ShowAge()
{
	int age = 23;
	cout << "Age is:" << age << endl;
}
void ShowIndex()
{
	int index =10;
	cout << "Index is : " << index << endl;
}

函数的参数及返回值

空函数

没有参数和返回值,函数的作用域为空的函数就是空函数。

void setWorkSpace() {}

空函数存在的意义是:在程序设计中往往需要根据确定若干模块,分别由一些函数来实现。二在第一阶段只设计最基本的模块,其他一些次要功能或锦上添花的功能则在以后需要时陆续不上。在编写程序的开始阶段,可以在将来准备扩充功能的地方写上一个空函数,这些函数没有开发完成,先占一个位置,以后用一个编好的函数代替它。这样做程序结构清楚,可读性好,保证以后扩充新功能方便,对程序结构影响不大。

形参与实参

函数定义时如果参数列表为空,说明函数是无参函数,如果参数列表不为空,就称为带参数函数。带参数函数中的参数在函数声明和定义时被称为“形式参数”,简称形参。在函数被调用时被赋予具体值,具体的值被称为“实际参数”,简称实参。
实参与形参的个数应相等,类型应一致。实参与形参按顺序对应,函数被调用时会一一传递数据。
形参与实参的区别:
(1)在定义函数中指定的形参,在未出现函数调用时他们并不占用内存中的存储单元。只有在发生函数调用时,函数的形参才被分配内存单元,在调用结束后,形参所占用的内存单元也被释放。
(2)实参应该是确定的值,在调用时将实参的值赋值给形参,如果形参是指针类型,就将地址值传递给形参。
(3)实参与形参的类型相同。
(4)实参与形参之间是单项传递,只能由实参传递给形参,而不能由形参传回来给实参。

默认参数

在调用有参数时,如果经常需要传递同一个值到调用函数,在定义函数时,可以为参数设置一个默认值,这样在调用函数时可以省略一些参数,此时程序将采用默认值作为函数的实际参数。如:

void OutputInfo(const char* pchData="one world,one dream!")
{
	cout << pchData << endl;
}

可变参数

库函数printf的参数就是一个可变参数,它的参数列表会显示“…”省略号。printf函数原型格式如下:

CRTIMP int_cdec1 printf(const char*,…);

省略号参数代表的含义是函数的参数时不固定的,可以传递一个或多个参数。
对于可变参数的函数,在定义函数时需要一一读取用户传递的实际参数。可以使用va_list类型和va_start、va_arg、va_end 三个宏读取传递到函数中的参数值,使用可变参数需要引用STDARG.H头文件。
实例02 带有可变参数的函数应用

#include <iostream>
#include <STDARG.H>
using namespace std;
void OutputInfo(int num,...)
{
	va_list arguments;
	va_start(arguments,num);
	while(num--)
	{
		char* pchData = va_arg(arguments,char*);
		int iData=va_arg(arguments,int);
		cout << pchData << endl;
		cout << iData << endl;
	}
	va_end(arguments);
}
void main()
{
	OutputInfo(2,"Beijing",2008,"Olympic Games",2008);
}

返回值

函数的返回值是指函数被调用之后,执行函数体中的程序段所取得的并返回给主调函数的值,函数的返回值通过return语句返回给主调函数。
return语句一般形式如下:

return (表达式);

语句将表达式的值返回给主调函数。
关于返回值的说明:
(1)函数返回值的类型和函数定义中函数的类型标识符应保持一致。如果两者不一致,则以函数类型为准,自动进行类型转换。
(2)如函数值为整型,在函数定义时可以省去类型标识符。
(3)在函数中允许有多个return语句,但每次调用只有一个return语句被执行,因此只能返回一个函数值。
(4)不返回函数值的函数,可以明确定义为“空函数”,类型标识符为“void”。
(5)类型标识符为void的函数不能进行赋值运算及值传递。

函数调用

声明完函数后就需要在源代码中调用该函数,整个函数的调用过程称为函数调用。
(1)首先被调用的函数必须是已经存在的函数(库函数或用户自己定义的函数);
(2)如果使用库函数,还需要使用预编译指令#include将库函数对应的头文件引入;
(3)如果使用用户自定义函数,一般应该在调用该函数之前对被调用的函数做声明。

传值调用

主调函数和被调用函数之间有数据传递关系,主调函数将实参数值赋值给被调用函数的形参,这种调用方式被称为传值调用,如果传递的实参是结构体对象,值传递方式的效率低下,可以通过传指针或使用变量的引用来替换传值调用。传值调用时函数调用的基本方式。
实例03 传值调用

#include <iostream>
void swap(int a,int b)
{
	int tmp;
	tmp = a;
	a = b;
	b = tmp;
}
void main()
{
	int x,y;
	cout << "输入两个数:" << endl;
	cin >> x;
	cin >> y;
	if(x<y)
	{
		swap(x,y);
	}
	cout << "x=" << x << endl;
	cout << "y=" << y << endl;
}

递归调用

直接或间接调用自己的函数称为递归函数。
使用递归方法解决问题的特点是:问题描述清楚、代码可读性强、结构清晰,代码量比使用非递归方法少。缺点是递归程序的运行效率低。
递归函数必须定义一个停止条件,否则函数永远递归下去。
实例04 汉诺塔问题
A上的n个圆盘移动到C上可以分为三个步骤:
(1)把A上的n-1个圆盘移到B上;
(2)把A上的一个圆盘移到C上;
(3)把B上的n-1个圆盘移到C上。

#include <iostream>
#include <iomanip>
using namespace std;
long lCount;
void move(int n,char x,char y, char z)
{
	if(n==1)
		cout << "Times:" << setw(2) << ++lCount << " " << x << "->" << z << endl;
	else
	{
		move(n-1,x,z,y);
		cout << "Times:" << setw(2) << ++lCount << " " << x << "->" << z << endl;
		move(n-1,y,x,z);
	}
}
void main()
{
	int n;
	lCount=0;
	cout << "please input a int number:" << endl;
	cin >> n;
	move(n,'a','b','c');
}

变量作用域

根据变量声明的位置可以将变量分为局部变量及全局变量,在函数体定义内的变量称为局部变量,在函数体外定义的变量称为全局变量。
变量都有它的生命周期,全局变量在程序开始时创建并分配空间,在程序结束时释放内存并销毁;局部变量是在函数调用时创建,并在栈中分配内存,在函数调用结束后销毁并释放。

重载函数

重载函数就是指多个函数具有相同的函数标识名,而参数类型或参数个数不同的函数,函数调用时,编译器以参数的类型及个数来区分调用哪个函数。
实例05 重载函数的使用

#include <iostream>
using namespace std;
int add(int x, int y)
{
	cout << "Int add" << endl;
	return x+y;
}
double add(double x, double y)
{
	cout << "Double add" << endl;
	return x+y;
}
int main()
{
	int ivar = add(5,2);
	float fvar = add(5.0,2.0);
	return 0;
}

在定义重载函数时,应注意函数的返回值类型不作为区分重载函数的一部分。

内联函数

内联函数是指inline关键字修饰的函数,编译器会在每个调用该函数的地方展开一个函数的副本。
使用内联函数可以减少函数调用带来的开销。在函数实现代码很简短或者调用该函数次数相对较少的情况下应该将函数定义为内联函数,一个递归函数不能在调用点完全展开,一个一千行的函数也不大可能在调用点展开,内联函数只能在优化程序时使用。

变量的存储类别

存储类别是变量的属性之一,C++语言定义了4中变量的存储类别,分别是auto变量、static变量、register变量和extern变量。变量存储方式不同会使变量的生存期不同,生存期表示了变量存在的时间,生存期和变量作用域是从时间和空间这两个角度来描述变量的特性。

auto变量

auto变量存储类型是C++语言程序中默认的存储类型,函数内未加存储类型说明的变量均视为auto变量,auto变量可以省去关键字auto。
auto变量具有以下特点:
(1)auto变量的作用域仅限于定义该变量的个体内。
(2)auto变量术语动态存储方式,变量分配的内存是在栈中,当函数调用结束后,auto变量的值会被释放。
(3)由于auto变量的作用域和生存期都局限于定义它的个体内。

static变量

在声明变量前加关键字static,可以将变量声明成静态变量。静态局部变量的值在函数调用结束后不消失,静态全局变量只能在本源文件中使用。
静态变量属于静态存储方式,它具有以下特点:
(1)静态变量在函数内定义,在程序退出时释放,在程序整个运行期间都不释放。
(2)静态变量的作用域与auto变量相同,在函数内定义就在函数内使用,尽管该变量还继续存在,但不能使用它,如再次调用定义它的函数时,它又可以继续使用。
(3)编译器会为静态局部变量赋予0值。
实例06 static变量的使用

#include <iostream>
using namespace std;
int add(int x)
{
	static int n = 0;
	n += x;
	return n;
}
void main()
{
	int i,j,sum;
	cout << "Input the number:" << endl;
	cin >> i;
	cout << "The result is:" << endl;
	for(j=1;j<=i;j++)
	{
		sum = add(j);
		cout << j << ":" << sum << endl;
	}
}

register变量

通常变量的值存放在内存中,当对一个变量频繁读写时,需要反复方位内存,则花费大量的存储时间,为了提高效率,C++语言可以将变量声明为寄存器变量,这种变量将局部变量的值存在CPU中的寄存器中,使用时不需要访问内存,而直接从寄存器中读写。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值