目录:
- 内联函数
- 引用变量
- 将引用变量作为函数参数
- 使用引用作为形参,会改变对应实参的值以及左值的概念
- 将引用应用于结构
- 为何要使用引用
- 将引用用于类和对象
- 对象、继承和引用
- 何时使用按值传递、按指针传递和按引用传递
- 默认参数
- 函数重载
- 重载示例
- 函数模板
- 重载的模板
- 显式具体化
- 实例化和具体化包含的知识点为结构数组,指针数组,模板等
- 自己选择使用哪个函数模板
- 模板函数的优化,设计到相关函数的引进
内联函数
/*
01)c语言中的宏,例如:
#define SQUARE(X) X*X
a = SQUARE(5.0); //等价于a = 5.0*5.0 正常
b = SQUARE(4.5+7.5) //等价于b = 4.5+7.5*4.5+7.5,则不
正常了,可以通过#define SQUARE(X) ((X)*(X))方法改进
d = SQUARE(c++) //等价于d = c++ * c++ c最后的值会增加两次 假如c等于3 c++ * c++就等价于3*4 最后c等于5,
而在宏定义出现类似的错误的时候,可以考虑使用内联函数
02)要是有内联函数,要采取下述措施之一:
在函数生命前加上关键字inline
在函数定义前加上关键字inline
通常的做法是省略原型(函数声明),将整个定义放在本应提供原型(函数声明)的地方
03)内敛函数可以提高程序的执行速度,代价是 程序占用的
内存增加,假如程序要在10个不同的地方调用同一个内联 函数,则该程序将包含该函数代码的十个副本
04)以下代码中也包含了c++后缀的使用技巧,需要注意的一个点
*/
附图说明普通函数调用和内联函数调用的区别
1 #include <iostream> 2 3 using namespace std; 4 5 //内联函数的定义 6 inline double square(double x) { return x * x; } //将整个函数定义放在了一行,如果函数定义占用多行,那么使用内联函数就不太合适 7 8 int main() 9 { 10 double a, b; 11 double c = 13.0; 12 13 a = square(5.0); //内联函数的调用 14 b= square(4.5+7.5); //内联函数的调用 15 cout << "a = " << a << endl; 16 cout << "a = " << b << endl; 17 18 cout << "c = " << c; 19 double d = square(c++); //后缀运算符是先使用后修改,所以c先将13传入内联函数,后将自身值递增为14 20 cout << " c square = " << d << endl; 21 22 cout << "Now c = " << c << endl; 23 24 system("pause"); 25 return 0; 26 }
执行结果:
引用变量
/*
01)c和c++使用&来指示变量的地址。c++赋予了&另一个含义,将其用来声明印用
int rats;
int & rodents = rats; //将rodents作为rats的别名 int &表示是指向int的引用,其中&不是地址运算符
上述声明允许将rats和rodents呼唤,他们指向相同的内存单元,将rodets加1将会影响两个变量
更准确的说rodents++操作将一个有两个名称的变量加1
02)必须在声明引用时将其初始化 如:
int rats;
int & rodents;
rodents = rats; //这样做是错误的
03)引用和指针是有区别的
int rets;
int* parts = &rats; //声明并初始化一个指针parts,该指针指向rats
int & rodents = rats; //声明并初始化一个引用rodents,使rodents成为rats的别名
这样表达式rodents和*parts都可以和rats呼唤,而表达式&rodents和parts也都可以和&rats互换
04)引用更接近于const指针,必须在创建时进行初始化,一旦与某个变量关联起来,就一直效忠于它
也就是说:int & rodents = rats;
实际上是该代码的伪装表示:int* const pr = &rats;
其中引用扮演的角色与表达式*pr相同
05)int rats = 101;
int* pt = &rats; //声明并初始化一个指针parts,该指针指向rats
int & rodents = *pt; //由于*pt就等价于rats,所以该句的意思就是声明并初始化一个引用rodents,使rodents成为rats的别名
int business = 50;
pt = &business; //pt改为指向business,但是rodents还是指向rats
*/
1 #include <iostream> 2 3 using namespace std; 4 5 int main() 6 { 7 int rats = 101; 8 int & rodents = rats; //声明并初始化一个引用rodents,使rodents成为rats的别名 9 10 cout << "value of rats is: " << rats << "; " << "Address of rats is: " << &rats << endl; 11 cout << "value of rodents is: " << rodents << "; " << "Address of rodents is: " << &rodents << endl; 12 13 int business = 50; 14 rodents = business; //等价于rats = business,执行完此句之后,rats和rodents的值都会改变为50,且二者的地址相同,但二者的地址和business是不一样的 15 cout << "value of business is: " << business << "; " << "Address of business is: " << &business << endl; 16 cout << "value of rats is: " << rats << "; " << "Address of rats is: " << &rats << endl; 17 cout << "value of rodents is: " << rodents << "; " << "Address of rodents is: " << &rodents << endl; 18 19 system("pause"); 20 return 0; 21 }
执行结果为:
将引用变量作为函数参数
按值传递和按引用传递的区别如下图所示:
由于简单,直接上代码了吧那就:
1 //使用引用变量、指针、和普通变量作为函数参数交换形参的值 2 #include <iostream> 3 4 void swapr(int & a, int & b); //声明参数为引用变量的函数 5 void swapp(int* a, int* b); //声明参数为指针的函数 6 void swapv(int a, int b); //声明参数为普通变量的函数 7 8 int main() 9 { 10 using namespace std; 11 12 int wallet1 = 200; 13 int wallet2 = 300; 14 15 cout << "原始数据为:wallet1 = " << wallet1 << endl; 16 cout << "原始数据为:wallet2 = " << wallet2 << endl; 17 18 swapr(wallet1, wallet2); //调用参数为引用变量的函数 19 cout << "调用参数为引用变量的函数:wallet1 = " << wallet1 << endl; 20 cout << "调用参数为引用变量的函数:wallet2 = " << wallet2 << endl; 21 22 swapp(&wallet1, &wallet2); //调用参数为指针的函数 23 cout << "调用参数为指针的函数:wallet1 = " << wallet1 << endl; 24 cout << "调用参数为指针的函数:wallet2 = " << wallet2 << endl; 25 26 swapv(wallet1, wallet2); //调用参数为普通变量的函数 27 cout << "调用参数为普通变量的函数:wallet1 = " << wallet1 << endl; 28 cout << "调用参数为普通变量的函数:wallet2 = " << wallet2 << endl; 29 30 system("pause"); 31 return 0; 32 } 33 34 void swapr(int & a, int & b) //该子函数修改的是主函数中的值,假如在主函数中调用该子函数时候传入了主函数中的值 35 { 36 int temp = a; 37 a = b; 38 b = temp; 39 } 40 void swapp(int* a, int* b) ////该子函数修改的是主函数中的值,假如在主函数中调用该子函数时候传入了主函数中的值 41 { 42 int temp = *a; 43 *a = *b; 44 *b = temp; 45 } 46 void swapv(int a, int b) //该子函数只是复制了传入该子函数的值给a、b,并交换了a和b的值,并没有交换主函数中的wallet1和wallet2的值 47 { 48 int temp = a; 49 a = b; 50 b = temp; 51 }
执行结果为:
使用引用作为形参,会改变主函数中的实参的值
/*
01)左值:左值参数是可被引用的数据对象,例如:变量、数组元素、结构成员、引用和接触引用的指针都是左值
非左值:包括字面常量(用引号括起的字符串除外,它们由地址表示)和含有多项式的表达式
02)应尽可能在声明函数中的形参时候使用const,原因如下
I 使用const可以避免无意中修改数据
II 使用const能使函数能够处理const和非const实参,否则子函数就只能接收非const实参(假如子函数形参类型不是const)
*/
1 #include <iostream> 2 3 double cube(double a); //声明一个普通函数 4 double refcube(double &ra); //声明一个形参为引用的函数 5 6 int main() 7 { 8 using namespace std; 9 10 double x = 3.0; //定义常规变量 11 12 cout << cube(x) << " = cube of " << x << endl; //调用普通函数,此时x的值不会改变 13 14 cout << refcube(x) << " = cube of " << x << endl; //但是这样将refcube(x)和x一起打印的话还是x的值是不变的,执行完这一句之后x = ra的值即27 15 16 double z = refcube(x); //调用引用函数,此时x的值会随着子函数中ra的值的改变而改变 此时x=27 17 cout <<z<< " = cube of " << x << endl; //打印19683= cube of 19683 18 19 /*如果ra是一个变量的别名(即引用),则实参应该是变量,而不应该是表达式*/ 20 //double z1 = refcube(x+10); //不合法 21 //double z1 = refcube(10); //不合法 22 double yo[3] = { 2.2,3.3,4.5 }; //声明一个数组 23 24 double z1 = refcube(yo[2]); //合法 数组元素 25 cout << "refcube(yo[2]) = " << z1 << endl; 26 27 /* 有关左值的概念 */ 28 double side = 3.0; 29 double* pd = &side; //创建指向side的指针pd 30 double & rd = side; //创建引用变量,rd即等价于side 31 long edge = 5L; //创建长型变量,注意要在数字最后加上字母L 32 double lens[4] = { 2.0,5.0,10.0,12.0 }; //创建数组 33 34 double c1 = refcube(side); //ra is side 35 double c2 = refcube(lens[2]); //ra is lens[2] 36 double c3 = refcube(rd); //ra is rd is side 37 double c4 = refcube(*pd); //ra is *pd is side 38 39 double c5 = refcube(edge); //不合法,因为ra是double类型的,而edge是long类型的 40 double c6 = refcube(7.0); //7.0是非左值,不合法 41 double c7 = refcube(side + 7.0); //side+7.0是包含多项式的表达式,是非左值,不合法 42 //c++遇到上述三种类型,就会创建类型正确的匿名变量,将函数调用的参数的值传递给改匿名变量,并让参数来引用改变量 43 44 45 46 system("pause"); 47 return 0; 48 } 49 50 double cube(double a) 51 { 52 /*a = a * a*a;*/ 53 a = a*a * a; 54 55 return a; 56 } 57 double refcube(double &ra) 58 { 59 //ra = ra * ra*ra; 60 ra = ra* ra * ra; //也可以这么写 ra *= ra*ra; 61 62 return ra; 63 }
执行结果为:
将引用应用于结构
/*
01) 使用结构引用参数的方式于使用基本便令引用方式相同,只需在结构参数使用引用运算符&即可
02) 假如有如下结构:
struct free_throws
{
std::string name;
string made;
int attemps;
float percent;
};
则可以这样声明子函数,在子函数中将指向改结构的引用,作为参数
void set_pc(free_throws & ft); //可以更改结构中的参数
void display(const free_throws & ft); //加上const则不能更改结构中的参数
*/
1 #include <iostream> 2 #include <string> 3 4 5 struct free_throws 6 { 7 std::string name; //新建一个string型字符串变量name 8 int made; 9 int attemps; 10 float percent; 11 }; 12 13 void display(const free_throws & ft); //声明一个函数,形参为指向结构free_throws的引用ft,但是不可以通过ft来改变结构中的值,此处的ft为const引用参数 14 void set_pc(free_throws & ft); //声明一个函数,形参为指向结构free_throws的引用ft 15 free_throws & accumulate(free_throws & target, const free_throws & source); //声明一个返回值为free_throws结构引用的函数accumulate,形参为两个指向结构的引用 16 17 int main() 18 { 19 //初始化结构变量 20 free_throws one = { "Ifelsa Branch",13,14 }; //没有被赋值的就默认为0,比如以下均没有对percent赋值,则percent均为0 21 free_throws two = { "Andor Knott",10,16 }; 22 free_throws three = { "Mininie Max",7,9 }; 23 free_throws four = { "Whily Looper",5,9 }; 24 free_throws five = { "Long Long ago",6,14 }; 25 free_throws team = { "Throwgoods",0,0 }; 26 free_throws dup; //定义结构dup,没有初始化 27 28 //01简单调用形参结构的子函数 29 set_pc(one); //调用子函数,参数为指向结构的引用 此句为填充one结构中percent的值 30 display(one); //调用子函数,参数为指向结构的引用 此句为显示整个one结构中的值 31 32 33 //02调用返回值为结构的子函数,但是这个返回值并没有使用,而是用子函数中的引用去修改主函数中结构的值 34 accumulate(team, one); //这一句的确是会返回一个结构,但是由于该函数的形参为引用,所以传入的team结构中的值也会被改变 35 //其中在accumulate子函数中,第二个引用为conts类型,对应one,只是 用以下one结构中的值,不会改变one中的值,如果在子函数中要求改变,会报错 36 //在accumulate子函数中,第二个参数为非const类型,故可以在子函数中更改team中的值,且在子函数中修改target的值就是修改team的值 37 display(team); 38 39 //03使用accumulate子函数的返回值,作为另外一子函数display的实参,accumulate子函数的返回值为引用,进一步说是结构引用 40 display(accumulate(team, two)); //使用accumulate(team, two)的返回值(team)作为display的实参 41 accumulate(accumulate(team, three),four); 42 display(team); 43 44 //04将返回值赋给一个没有初始化的结构 dup 45 dup = accumulate(team, five); 46 std::cout << "display(team): "; 47 display(team); 48 49 std::cout <<"Displaying dup after assignment: ' '"; 50 display(dup); 51 52 set_pc(four); //重新设置结构four中的percent的值 53 54 system("pause"); 55 return 0; 56 } 57 58 void display(const free_throws & ft) 59 { 60 using std::cout; 61 cout << "Name: " << ft.name << ' '; //其中' '表示换行,用endl也是可以的 62 cout << " Made: " << ft.made << ' '; 63 cout << "Attemps: " << ft.attemps << ' '; //' '表示制表符 64 cout << "Percent: " << ft.percent << ' '; 65 66 } 67 void set_pc(free_throws & ft) //由于没有对ft加限定符const,所以该子函数允许修改原结构中的变量的值 68 { 69 if (ft.attemps != 0) 70 ft.percent = 100.0f*float(ft.made) / float(ft.attemps); //100.0f表示100为float型 71 else 72 ft.percent = 0; //percent的值就被修改,而不用返回percent的值到主函数,是直接修改的主函数中的结构原型中的结构参数,而不是修改的副本 73 } 74 free_throws & accumulate(free_throws & target, const free_throws & source) 75 { 76 target.attemps += source.attemps; //赋值操作 77 target.made += source.made; //赋值操作 78 set_pc(target); //在子函数中调用子函数,重新对指向结构的引用target赋值 79 return target; //返回值为结构引用 或者说返回值为target,假如传入的是team,那么target就是team的引用,即target和team是等价的,返回target就是返回team了 80 }
执行结果为:
/*
01)对于srt_pc(one); 必须使用按引用传递参数,不可使用按值传递,如果使用按值传递,则修改不了结构one中的percent的值
02)另一种方法是使用指针参数并传递地址 *****
set_pc(&one)
......
void set_pc(free_throws* pt)
{
if (pt->attemps != 0)
pt->percent = 100.0f*float(pt->made) / float(pt->attemps); //100.0f表示100为float型
else
pt->percent = 0;
}
//注意:由于ft是指向结构的指针,所以只可以使用间接成员运算符->来访问结构中的成员
03)display(one); 由于只是显示结构中的内容,所以使用了一个const引用参数
为何要使用引用
/*
01)传统返回机制于安宅传递函数参数类似,计算关键字return后的表达式,并将结构返回给调用函数
从概念上说这个只被复制到一个临时位置,而调用程序将使用这个值
02)dup = acuumulate(team,five); //注意返回值就是team,因为传入的时候target是team的引用,那么target和team是等价的
如果accumulate返回的是一个结构,而不是指向结构的引用,将把整个结构复制到一个临时位置,再将
这个拷贝复制给dup。但在返回值为引用时,将直接把team复制到dup,效率会更高。
*/
将引用用于类和对象
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 string version1(const string & s1, const string & s2); //声明一个返回值为string类型字符串、形参为两个指向string类型变量的引用 7 const string & version2(string & s1, const string & s2); //声明一个返回值为指向const string类型变量的引用、形参也为两个引用的子函数 8 const string & version3(string & s1, const string & s2); 9 10 int main() 11 { 12 string input; //定义一个string类变量input 13 string copy; //定义一个string类变量input 14 string result; //定义一个string类变量input 15 16 cout << "请输入一个字符串或句子:"; 17 getline(cin, input); //此句是对于string字符串接收,而cin.getline(charr,20);中charr是一个char数组用于c风格 18 copy = input; //复制数据给copy 19 cout << "您的输入为:" << input << endl; 20 result = version1(input, "***"); 21 cout << "调用vision2后的结果字符串result为:" << result << endl; 22 cout << "调用vision2后的初始字符串input为:" << input << endl; 23 24 result = version2(input, "###"); //与version2(input,"###"); result = input;是等价的,因为s1等价于input改变s1就是改变temp的值 25 /* 26 对于 version2(input, "###");中的input和"###" 27 01)input是string类型的变量,传递到version2中对应string & s1,即s1是指向input的引用,合理 28 02)"###"是一个char类型的字符串(实际是一个指针,类型为const char*),那么将一个const char*赋给一个以用是否合理呢 29 这里需要说明的是:在c++中string定义了char*向string转换功能,这使得可以使用c等个字符串来初始化string对象, 30 在将"###"传递给string & s2时,c++就会将char*或者是const char*转换为string类,再赋值给string & s2,这样就合理了 31 03)将int型实参传递给const double & ra 也是先将int型实参转换为double型,再赋值给ra的 32 04)此时input的内容将会被改变!!! 33 */ 34 cout << "调用vision2后的结果字符串result为:" << result << endl; 35 cout << "调用vision2后的初始字符串input为:" << input << endl; 36 37 //result = version3(input, "@@@"); //会报错,因为在version3中返回值temp为临时变量,在执行完该子函数后,temp就会消失 38 //而此时要将一个消失了的变量赋值给result,故编译器会报错 39 40 system("pause"); 41 return 0; 42 } 43 44 string version1(const string & s1, const string & s2) 45 { 46 string temp; 47 temp = s2 + s1 + s2; //将传入的字符串合并在一起 48 return temp; //返回刚刚合并的字符串 49 } 50 const string & version2(string & s1, const string & s2) 51 { 52 s1 = s2 + s1 + s2; 53 return s1; 54 } 55 56 const string & version3(string & s1, const string & s2) 57 { 58 string temp; 59 60 temp = s2 + s1 + s2; 61 62 return temp; //如果返回值不是引用,是普通的变量,在使用result = version3(input, "@@@");时不会出错 63 //函数试图引用已释放的内存 64 }
注意:在返回值为引用的时候,不可以将在子函数内部定义的一个临时变量返回,否则在主函数中调用时候,会报错
不调用只是会发出警告,详见上面的代码中的version3子函数
执行结果为:
对象、继承和引用
/*
01)将特性从一个类传递给另一个类的语言特性被称为继承,比如ofstream对象可以使用ostream类的方法
这使得文件输入/输出格式与控制台(屏幕输出)输入输出相同
02)那么ostream是基类(因为ofstream是建立在它的基础之上的),而ofstream是派生类(因为它是从ostream派生而来的)
派生类继承了基类的方法,这意味着ofstream对象可以使用基类的特性,如格式化方法precision()和setf()
03)继承的另一个特征是,基类引用可以指向派生类对象,而无需进行强制转换
这种特征的结果是,可以定义一个接收基类引用作为参数的函数,调用该函数时,可以将基类对象作为参数
也可以将派生类对象作为参数。如参数类型为ostream &的函数可以接收ostream对象(如cout)或
自己声明的ofstream对象作为参数
*/
使用一个函数实现打印到屏幕和写入到文件(函数参数不用,使用ostream对象cout和类fstream对象fout),由于fstream是派生类,ostream是基类,派生类可以使用基类的方法,比如格式化方法precision()和setf()方法
1 #include <iostream>
2 #include <fstream> //for ofstream(写文本) 和ifstream(读文本) 的使用
3 #include <cstdlib> //for exit()
4
5 using namespace std;
6
7 void file_it(ostream & os, double fo, const double fe[], int n);//声明一个形参为指向ostream类对象的引用os的函数
8
9 const int LIMIT = 5; //声明一个常量
10
11 int main()
12 {
13 ofstream fout; //声明一个类fstream的对象fout
14 const char* fn = "eo-data.txt"; //声明一个指向eo-data.txt字符串的指针fn
15 fout.open(fn); //将fout和文件eo-data.txt关联起来
16
17 if (!fout.is_open()) //判断文件是否打开失败
18 {
19 cout << "Can't open " << fn << ". bye.
";
20 exit(EXIT_FAILURE); //退出程序
21 }
22 double objective;
23 cout << "Enter the focal lengths of your telescope objective in mm:";
24 cin >> objective; //输入显微镜的焦距(focal)
25 double eps[LIMIT]; //新建一个数组,用来盛放输入的数据
26 cout << "Enter the focal lengths,in mm,of " << LIMIT << " eyepieces:
"; //eyepieces目距
27 for (int i = 0; i < LIMIT; i++)
28 {
29 cout << "Eyepieces #" << i + 1 << ";";
30 cin >> eps[i]; //接收输入的参数
31 }
32 file_it(fout, objective, eps, LIMIT); //参数为fout(写入到文件中)的函数调用
33 file_it(cout, objective, eps, LIMIT); //参数为cout(打印到屏幕中)的函数调用
34 cout << "Done
";
35
36 system("pause");
37 return 0;
38 }
39
40 //os是指向cout或fout的引用,ostream是一个类名
41 // ostream os; //创建ostream的对象os
42 // ostream & os = cout; //创建指向cout的引用os(os也是一个ostream对象,cout也是ostrema对象)
43 void file_it(ostream & os, double fo, const double fe[], int n)
44 {
45 ios_base::fmtflags initial; //方法setf()返回调用它之前有效的所有格式,ios_base::fmtflags是存储这种信息所需的数据类型名称
46 initial = os.setf(ios_base::fixed); //保存最初的格式状态,并将这种状态赋值给initial
47 os.precision(0);
48 os << "Focal length of objective: " << fo << "mm
";
49 os.setf(ios_base::showpoint); //将对象(os)置于显示小数点的模式,即使小数部分为零,解析来就显示小数点后面的0,否则是不显示小数点后面的0的
50 os.precision(1); //方法precision()用于指定显示多数为小数(假设对象处于定点模式下)
51 os.width(12); //设置下一次输出操作使用的字段宽度,这种设置只在显示下一个值时有效,然后恢复到默认设置
52 os << "f.1.eyepiece"; //默认字段宽度为0,这意味着刚好能容纳下要显示的内容
53 os.width(15);
54 os << "magnification" << endl;
55 for (int i = 0; i < n; i++)
56 {
57 os.width(12);
58 os << fe[i];
59 os.width(15);
60 os << int(fo / fe[i] + 0.5) << endl; //焦距除以目距就是显微镜的放大倍数
61 }
62 os.setf(initial); //恢复原始的输出或者是写入设置
63 }
执行结果:
何时使用按值传递、按指针传递和按引用传递
/*
使用引用参数的原因主要有两个:
01)程序员能够修改调用函数中的数据对象
02)通过传递引用而不是整个数据对象,可以提高程序的运行速度
什么时候用引用、什么时候用指针、什么时候用按值传递呢,下面是一些指导原则:
01)对于使用传递的值而不做修改的函数(不修改主函数中的数据)
A 如果数据对象很小,如内置数据类型或小型结构,则按值传递
B 如果数据对象是数组,则使用指针,因为这是唯一的选择,并将指针声明为指向const的指针
C 如果数据对象是较大的结构,则使用const指针或const引用,以提高程序效率,这样可以节省赋值结构所需的时间
D 如果数据对象是类对象,则使用const指针或const引用。类设计的语义常常要求使用引用,
传递类对象参数的标准方式就是按引用传递
02)对于修改调用函数(主函数)中数据的函数,即修改主函数中的数据
A 如果数据对象是内置数据类型,则使用指针。如果看到fix_it(int & x),由函数名字可知,是要修改主函数传入的值
其中x就是内置数据
B 如果数据对象是数组,则只能使用指针
C 如果诗句对象是结构,则使用引用或指针
D 如果数据对象是类对象,则使用引用
*/
默认参数
/*
01)默认参数定义:指当函数调用中省略了实参时,自动使用的一个值,如void wow(int n)设置成n为默认值为1
则函数调用wow()相当于wow(1);
02)默认参数的作用: 提高函数调用的灵活性,例如:假设有一个名为left()的函数,它将字符串和n作为参数
并返回该字符串的前n个字符,更准确是说是返回一个指针,该指针指向前n个字符。例如left("theiry",3)
将返回字符串"the",现在假设第二个参数的默认值被设置为1,则left("theiry",3)仍会正常工作,只不过3
会覆盖默认值1。而且left("theiry")仍不会出错,因为默认值为1,并且left("theiry")返回字符t。
03)如何设置默认值:通过函数原型(函数的声明),例如left()函数的声明如下:
char* left(const char* str, int n=1); //即表示n的默认值为1,且函数的返回值为char*即字符串的地址
04)声明规则:要为某个函数添加默认值,那么在函数声明中右边所有的参数都提供默认值
int harpo(int n, int m=4, int j=5); //有效,右边全是默认值形式
int chico(inr n, int m=6,int j); //无效,因为m赋了默认值,但是在m的右边有没有赋默认值的j
int groucho(int k=1,int m=2,int j=3); //有效
05)调用方法:(假如有函数harpo()的声明:int harpo(int n, int m=4, int j=5);)
int beeps = harpo(2); //等价于harpo(2,4,5); m和j的默认值都不覆盖掉
int beeps = harpo(2,8); //等价于harpo(2,8,5); 只是覆盖掉m的默认值
int beeps = harpo(8,7,6); //等价于harpo(8,7,6); 全部覆盖掉默认值
int beeps = harpo(8,,6); //不合法!!
06)在函数定义的时候,默认参数不可以再次赋值!!只是在声明的时候说明一下就好了
*/
1 #include <iostream> 2 const int ArSize = 80; 3 char* left(const char* str, int n = 1); //声明一个函数,返回值为char*(一个字符串(地址)),有一个默认参数n,默认值为1 4 5 int main() 6 { 7 using namespace std; 8 char sample[ArSize]; //定义一个字符串数组 9 cout << "请输入一个字符串:"; 10 cin.getline(sample, ArSize); //输入到sample中,可输入的最大字符数为ArSize 11 //cin.get(sample, ArSize); 12 cout << "您输入的字符串为:" << sample << endl; 13 char* ps = left(sample, 4); //子函数调用,3将覆盖掉默认值 14 cout << "子函数调用后截取的字符串为:" << ps << endl; 15 delete[] ps; //释放空间 16 17 system("pause"); 18 return 0; 19 } 20 //传递给left()函数的第一个参数,只能是char型字符串或数组 21 char* left(const char* str, int n) 22 { 23 char* pa = new char[n+1]; //只能定义一个指针,然后让该指针指向一个内存空间 24 pa[n] = '