函数和函数模板

一、函数的参数及其传递方式

C++的函数传递有两种传递方式:传值和伟引用。传值分为传“对象值”和“对象地址值”,“对象值”是指对象的数据成员值,“对象地址值”是指对象的首地址值。伟引用其实是传对象的地址。

注意:传地址值传递的是值,不是地址;传地址传的是地址,不是地址值。传递对象地址值是使用对象指针作为参数,传递对象地址是使用对象引用作为参数。

1、对象作为函数参数

将对象作为函数参数,是将实参对象的值传递给形参对象,这种传递是单向的。形参拥有实参的备份,当在函数中改变形参的值时,改变的是这个备份的值,不会影响原来实参的值,这种传值方式可以防止被调用的函数改变参数的原始值。

#include <iostream>
#include <string>
using namespace std;
void example1();
void swap1(string,string);//声明交换方法的函数原型
int main(){
	example1();
	return 0;
}
 
void example1(){
	string s1("过去"),s2("现在");//定义对象s1和s2
	cout << "交换之前:" << s1 << " " << s2 << endl;
	swap1(s1,s2);//使用传值方式传递s1和s2的数据成员值
	cout << "交换之后返回主函数:" << s1 << " " << s2 << endl;
	/**
	 * 交换之前:过去 现在
	 * 交换之后:现在 过去
	 * 交换之后返回主函数:过去 现在
	 */
}
 
void swap1(string s1,string s2){
	string temp = s1;
	s1 = s2;
	s2 = temp;
	cout << "交换之后:" << s1 << " " << s2 << endl;
};

2、对象指针作为函数参数

将指向对象的指针作为函数参数,形参是对象指针,实参是对象的地址值。虽然参数传递方式仍然是传值,但因为形参传递的就是实参本身,所以当在函数中改变形参的值时,改变的就是原来实参的值。传对象地址值要用到对象指针,常使用的传对象地址值的方式,如传递类或结构对象的地址值、传递数组名。

void example2();
void swap2(string *,string *);
int main(){
	example2();
	return 0;
}
 
void example2(){
	string s1("过去"),s2("现在");
	cout << "交换之前:" << s1 << " " << s2 << endl;
	swap2(&s1,&s2);//使用传地址值的方式传递s1和s2的地址值
	cout << "交换之后返回主函数:" << s1 << " " << s2 << endl;
	/**
	 * 交换之前:过去 现在
	 * 交换之后:现在 过去
	 * 交换之后返回主函数:现在 过去
	 */
}
 
void swap2(string *s1,string *s2){//string类的对象指针s1和s2作为参数
	string temp = *s1;
	*s1 = *s2;
	*s2 = temp;
	cout << "交换之后:" << *s1 << " " << *s2 << endl;
}

因为实参和形参的地址相同,所以改变形参就是改变实参。下面举例传递数组名:

void example3();
void swap3(int []);
int main(){
	example3();
	return 0;
}
 
void example3(){
	int a[] = {8,3};
	cout << "交换之前:" << a[0] << " " << a[1] << endl;
	swap3(a);//传递数组名a也就是传递指针
	cout << "交换之后返回主函数:" << a[0] << " " << a[1] << endl;
	/**
	 * 交换之前:8 3
	 * 交换之后:3 8
	 * 交换之后返回主函数:3 8
	 */
}
 
void swap3(int a[]){//使用数组名a也就是指针名作为函数参数
	int temp = a[0];
	a[0] = a[1];
	a[1] = temp;
	cout << "交换之后:" << a[0] << " " << a[1] << endl;
}

数组名就是数组指针名,数组指针名指向数组首地址,所以相当于传地址值,可以实现交换。

3、引用作为函数参数

使得引用作为函数,在函数调用时,实参对象名传给形参对象名,形参对象名就成为实参对象名的别名,实参对象和形参对象代表同一个对象,所以改变形参对象的值就是改变实参对象的值。

实际上,在传递地址时,是把实参对象的地址传给形参对象,使用形参对象的地址取实参对象的地址,从而使用形参对象和实参对象共享一个单元,这就是地址传递方式。

void example4();
void swap4(string &,string &);
int main(){
	example4();
	return 0;
}
 
void example4(){
	string s1 = "过去",s2 = "现在";
	cout << "交换之前:" << s1 << " " << s2 << endl;
	swap4(s1,s2);//使用传地址的方式传递s1和s2的引用地址
	cout << "交换之后返回主函数:" << s1 << " " << s2 << endl;
	/**
	 * 交换之前:过去 现在
	 * 交换之后:现在 过去
	 * 交换之后返回主函数:现在 过去
	 */
}
 
void swap4(string &s1,string &s2){//string类的引用对象s1和s2作为函数参数
	string temp = s1;
	s1 = s2;
	s2 = temp;
	cout << "交换之后:" << s1 << " " << s2 << endl;
}

系统向形参传递的是实参的地址而不是实参的值,通过引用参数,一个函数可以修改另一个函数内的变量,因为引用对象不是一个独立的对象,不单独占用内存单元,而对象指针要另外开辟内存单元(其内容是地址),所以传引用比传指针要更好。

4、默认参数

默认参数就是不要求程序设定该参数,而由编译器在需要时给该参数赋默认值,当程序员需要传递特殊值时,必须显式的指明。默认参数是在函数原型中说明的 ,默认参数可以多于一个,但必须放在参数序列的后面。
void example6();
void display1(int first,int second=2,int third=3);
int main(){
	example6();
	return 0;
}
 
void example6(){
	int first = 10,second = 20,third = 30;
	display1(first);//第一个参数值是:10,第二个参数值是:2,第三个参数值是:3
	display1(first,second);//第一个参数值是:10,第二个参数值是:20,第三个参数值是:3
	display1(first,second,third);//第一个参数值是:10,第二个参数值是:20,第三个参数值是:30
}
 
void display1(int first,int second,int third){
	cout << "第一个参数值是:" << first << ",第二个参数值是:" << second << ",第三个参数值是:" << third <<endl;
}

5、使用const保护数据

用const修饰传递参数,是通知函数,它只能使用参数而无权修改它。

void display2(const string &,string &);

二、内联函数

① 使用关键字inline可以让C++编译器在遇到对函数isnumber调用的时候,都用这个函数体替换调用表达式;

② 由于编译器必须知道内联函数的函数体,才能进行内联替换,因此内联函数必须在程序中第一次调用此函数的语句出现之前定义;

③ 如果程序多次调用某个函数,将会大大降低使用效率,使用内联函数能加快程序执行速度;

④ 具有循环语句、switch语句的函数不能说明为内联函数。

void example11();
inline int isnumber(char c){
	return (c>='0'&&c<='9')?1:0;
}
int main(){
	example11();
	return 0;
}
 
void example11(){
	char c;
	cin >> c;
	if(isnumber(c)){
		cout << "你输入的是一个0-9之间的数字!" << endl;
	}else{
		cout << "你输入的不是一个数字!" << endl;
	}
 
//	0
//	你输入的是一个0-9之间的数字!
}

三、函数重载和默认参数

函数重载可使一个函数名具有多种功能,即具有“多种形态”,这种特性被称为多态性。C++的多态性被直观的称为“一个名字,多种函数”,即每个函数除了函数名相同外,其他的都不相同。这时源代码只指明函数调用,而不说明具体调用哪个函数,编译器的这种连接方式称为动态联编,在动态联编中,只有程序运行时才能确定调用哪个函数。

如果编译器在编译时,能根据源代码调用固定的函数标识符,并用物理地址替代它们,这就称为静态联编,静态联编是在程序被编译时进行的。

void example12();
float max(float,float);//具有两个实型参数的函数原型
int max(int,int,int);//具有两个整型和一个实型参数的函数原型
int main(){
	example12();
	return 0;
}
 
void example12(){
	cout << "请输入两个实型数:" << endl;
	float f,g;
	cin >>f,cin>>g;
	float ff = max(f,g);
	cout << f << "和" << g << "中最大的实型数是:" << ff << endl;
 
	cout << "请输入三个整数:" << endl;
	int i,j,k;
	cin >>i,cin>>j,cin>>k;
	int ii = max(i,j,k);
	cout << i << "、" << j << "、" << k << "中最大的整数是:" << ii << endl;
}
 
float max(float f,float g){
	return f>g?f:g;
}
 
int max(int i,int j,int k){
	int temp = i>j?i:j;
	return temp>k?temp:k;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值