一、函数的参数及其传递方式
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;
}