[C++ Primer Plus] 第8章、函数探幽——(一)程序清单

8.1 C++内联函数

内联函数时C++为提高程序运行速度所做的一项改进,常规函数和内联函数的主要区别不在于编写方式,而在于C++编译器如何将它们组合到程序中。

编译过程的最终产品是可执行程序——由一组机器语言指令组成。运行程序时,操作系统将这些指令载入到计算机内存中,因此每条指令都有特定的内存地址。执行常规函数调用时,程序将在函数调用后立即存储该指令的内存地址,并将函数参数复制到堆栈,跳到标记函数起点的内存单元,执行函数代码(也许还需将返回值放入寄存器中),然后跳回到地址被保存的指令处,来回跳跃需要一定的开销。

对于内联函数,编译器将使用相应的函数代码替换函数调用,程序无需跳到另一个位置处执行代码,再跳回来。因此,内联函数的运行速度比常规函数稍快,但代价时需要占用更多的内存。

如果执行函数代码的时间比处理函数调用机制的时间长,则节省的时间只占很小一部分。如果执行代码时间很短,则内联调用可节省相对来说的大部分时间,但节省的时间绝对值并不大,除非该函数经常被调用。

写代码时,通常做法,是省略函数原型,直接将整个函数定义放在main()的前面,并在函数定义前加上关键字inline。该内联函数不能过长,且不能递归。

 1 #include<iostream>
 2 using namespace std;
 3 
 4 inline double square(double x) //inline表示内联函数
 5 {
 6     return x*x;
 7 }
 8 
 9 int main()
10 {
11     double a, b, c = 13.0;
12     a = square(5.0);
13     b = square(4.5 + 7.5);
14     cout << "a=" << a << ",b=" << b << endl;
15     cout << "c=" << c << ",c square=" << square(c++) << endl;
16     cout << "Now c=" << c << endl;
17     system("pause");
18     return 0;
19 }

[C++ Primer Plus] 第8章、函数探幽——(一)程序清单

 

 [C++ Primer Plus] 第8章、函数探幽——(一)程序清单

 

8.2 引用变量

8.2.1 创建引用变量

 引用是已定义的变量的别名。引用变量的主要用途是用作函数的形参,通过将引用变量作为参数,函数将使用原始数据,而不是其副本。这样除指针外,引用也为函数处理大型结构提供了一种非常方便的途径,同时对于设计类来说,引用也是必不可少的。

必须在声明引用变量时进行初始化。

 1 #include<iostream>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int rates = 101;
 7     int &rodents = rates;   //将rodents的类型声明为int&,即指向int变量的引用
 8     cout << "rates= " << rates;
 9     cout << ",rodents= " << rodents << endl;
10     rodents++;
11     cout << "rates= " << rates;
12     cout << ",rodents= " << rodents << endl;
13     cout << "rates address= " << &rates << endl;
14     cout << "rodents address= " << &rodents << endl;
15     cout << "****************************" << endl;
16     int bunnies = 50;
17     rodents = bunnies;
18     cout << "bunnies= " << bunnies;
19     cout << ",rates= " << rates;
20     cout << ",rodents= " << rodents << endl;
21     cout << "rates address= " << &rates << endl;      //rates和rodents的地址相同
22     cout << "rodents address= " << &rodents << endl;   
23     cout << "bunnies address= " << &bunnies << endl;
24 
25     system("pause");
26     return 0;
27 }

 [C++ Primer Plus] 第8章、函数探幽——(一)程序清单

将rodents初始化为*pt使得rodents指向rates,接下来将pt改为指向bunnies,并不能改变rodents引用的是rates。

 1 #include<iostream>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int rates = 101;
 7     int *pt = &rates;
 8     int &rodents = *pt;
 9     cout << rates << ' ' << rodents << ' ' << *pt << endl;
10     int bunnies = 50;
11     pt = &bunnies;
12     cout << rates << ' ' << rodents << ' ' << *pt << endl;
13     system("pause");
14     return 0;
15 }

[C++ Primer Plus] 第8章、函数探幽——(一)程序清单

 8.2.2 将引用用作函数参数

 按引用传递:使得函数中的变量名成为调用程序中的变量的别名。

按引用传递允许被调用的函数能够访问调用函数中的变量。

[C++ Primer Plus] 第8章、函数探幽——(一)程序清单

 

 8.2.3 引用的属性和特别之处

临时变量、引用参数和const

如果实参与引用参数不匹配,仅当参数为const引用时,C++将生成临时变量。

 [C++ Primer Plus] 第8章、函数探幽——(一)程序清单

 

 参数side,lens[2],rd和*pd都是有名称的,double类型的数据对象,因此可以为其创建引用,而不需要临时变量。然而,edge虽然是变量,类型却不正确,double引用不能指向long;参数7.0和side+10.0的类型都正确,但没有名称,在这些情况下,编译器都将生成一个临时匿名变量,并让ra指向它。这些临时变量只在函数调用期间存在,此后编译器便可以随意将其删除。

[C++ Primer Plus] 第8章、函数探幽——(一)程序清单

 8.2.4将引用用于结构

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 
 5 struct free_throws
 6 {
 7     string name;
 8     int made;
 9     int attempts;
10     float percent;
11 };
12 
13 void display(const free_throws &ft);
14 void set_pc(free_throws &ft);
15 free_throws & accumulate(free_throws &target, const free_throws &source);  //返回类型为free_throws &(引用),所以返回的不是target,而是最初传递给accumulate()的team对象
16 
17 int main()
18 {
19     free_throws one = { "If Branch", 13, 14 };
20     free_throws two = { "Andor Knott", 10, 16 };
21     free_throws three = { "Min Max", 7, 9 };
22     free_throws four = { "Whi Loo", 5, 9 };
23     free_throws five = { "Long Long", 6, 14 };
24     free_throws team = { "Throw", 0, 0 };
25     free_throws dup;
26 
27     set_pc(one);
28     display(one);
29     accumulate(team, one);
30     display(team);
31     display(accumulate(team, two));
32     accumulate(accumulate(team, three), four);
33     display(team);
34     dup = accumulate(team, five);       //如果accumulate()返回一个结构,而不是指向结构的引用,将把整个结构复制到一个临时位置,再将这个拷贝复制给dup。但在返回值为引用时,将直接把team复制到dup,其效率更高
35     cout << "Displaying team: " << endl;
36     display(team);
37     cout << "Displaying dup after assignment: " << endl;
38     display(dup);
39     set_pc(four);
40     accumulate(dup, five) = four;     //four赋给dup
41     cout << "Displaying dup after ill-advised assignment:" << endl;
42     display(dup);
43     system("pause");
44     return 0;
45 }
46 
47 void display(const free_throws &ft)
48 {
49     cout << "Name: " << ft.name << endl;
50     cout << "Made: " << ft.made << "t";
51     cout << "Attempts: " << ft.attempts << "t";
52     cout << "Percent: " << ft.percent << endl;
53 }
54 
55 void set_pc(free_throws &ft)
56 {
57     if (ft.attempts != 0)
58         ft.percent = 100.0f*float(ft.made) / float(ft.attempts);
59     else
60         ft.percent = 0;
61 }
62 
63 free_throws & accumulate(free_throws &target, const free_throws &source)
64 {
65     target.attempts += source.attempts;
66     target.made += source.made;
67     set_pc(target);
68     return target;
69 }

[C++ Primer Plus] 第8章、函数探幽——(一)程序清单

返回引用时需要注意的问题:

 返回引用时最重要的一点是,应避免返回函数终止时不再存在的内存单元引用。所以应避免编写以下代码:

const free_throws & clone2(free_throws & ft)
{
      free_throws newguy;
      newguy = ft;
      return newguy;
}

该函数返回一个指向临时变量(newguy)的引用,函数运行完毕后它将不再存在。同样,也应避免返回指向临时变量的指针。

为避免这种问题,最简单的方法是,返回一个作为参数传递给函数的引用。上面的accumulate()正是这样做的。

另一种方法是用new来分配新的存储空间。前面见过这样的函数,它使用new为字符串分配内存空间,并返回指向该内存空间的指针。

const free_throws & clone(free_throws & ft)
{
       free_throws *pt;
       *pt = ft;
       return *pt;
}

让指针pt指向该结构,因此*pt就是该结构。上述代码似乎会返回该结构,但函数声明表明,该函数实际上将返回这个结构的引用。这样便可以这样使用该函数:

free_throws & jolly=clone(three);

这使得jolly成为新结构的引用,不过这种存在一个问题:调用clone()隐藏了对new的调用,这使得以后很容易忘记使用delete来释放内存。

8.2.5 将引用用于类对象

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 
 5 string version1(const string &s1, const string &s2);
 6 const string & version2(string &s1, const string &s2);
 7 const string & version3(string &s1, const string &s2);
 8 
 9 int main()
10 {
11     string input;
12     string copy;
13     string result;
14     cout << "Enter a string: ";
15     getline(cin, input);
16     copy = input;       //C++中,string可以直接赋值
17     cout << "Your string as entered: " << input << endl;
18     result = version1(input, "***");                    //"***"是char *型,但可用于const string &的形参。此处2点需说明:1.string类定义了一种char*到string的转换功能,这使得可以使用C-风格字符串来初始化string对象。
19                                                         //2.前面提到过的如果引用参数是const,编译器在实参的类型不正确,但可以转换为正确的类型的情况下生成临时变量,使用转换后的实参值来初始化它,然后传递一个指向该临时变量的引用。
20     cout << "Your string enhanced: " << result << endl;
21     cout << "Your original string: " << input << endl;
22 
23     result = version2(input, "***");
24     cout << "Your string enhanced: " << result << endl;
25     cout << "Your original string: " << input << endl;
26 
27     cout << "Resetting original string." << endl;
28     input = copy;
29     result = version3(input, "@@@");
30     cout << "Your string enhanced: " << result << endl;
31     cout << "Your original string: " << input << endl;
32 
33     system("pause");
34     return 0;
35 }
36 
37 string version1(const string &s1, const string &s2)
38 {
39     string temp;
40     temp = s2 + s1 + s2;
41     return temp;         //返回main函数时,tmp不复存在,但tmp的内容被复制到临时存储单元
42 }
43 
44 const string & version2(string &s1, const string &s2)   //改变了s1的内容
45 {
46     s1 = s2 + s1 + s2;
47     return s1;
48 }
49 
50 const string & version3(string &s1, const string &s2)
51 {
52     string temp;
53     temp = s2 + s1 + s2;
54     return temp;        //返回main函数时,tmp内存已被释放,程序不能引用已经释放的内存
55 }

[C++ Primer Plus] 第8章、函数探幽——(一)程序清单

 此时该程序已经崩溃。

8.2.6 对象、继承和引用

 正如第6章介绍的,ofstream对象(文件用于处理输出的类)可以使用ostream类(控制台用于处理输出的类)的方法,这使得文件输入/输出的格式与控制台输入/输出相同。ostream是基类,ofstream是派生类,派生类继承了基类的方法,这意味着ofstream对象可以使用基类的特性。

继承的另一个特征是,基类引用可以指向派生类对象,而无需进行强制类型转换。这种特征的一个实际结果是,可以定义一个接受基类引用作为参数的函数,调用该函数时,可以将基类对象作为参数,也可以将派生类对象作为参数。

 1 #include <iostream>
 2 #include <fstream>
 3 #include <cstdlib>      //支持exit()函数
 4 using namespace std;
 5 
 6 void file_it(ostream &os, double fo, const double fe[], int n);
 7 const int LIMIT = 5;
 8 int main()
 9 {
10     ofstream fout;
11     const char *fn = "ex-data.txt";
12     fout.open(fn);        //若程序运行前ex-data.txt不存在,open()将新建一个名为ex-data.txt的文件;若程序运行前存在,open()将首先截断该文件,即将长度截短到0,丢其原来所有内容,然后将新的输出加入到该文件中
13     if (!fout.is_open())    //打开文件失败
14     {
15         cout << "Can't open " << fn << ".Bye.n";
16         exit(EXIT_FAILURE);    //异常退出
17     }
18     double objective;
19     cout << "Enter the focal length of your "
20         "telescope objective in mm: ";
21     cin >> objective;
22     double eps[LIMIT];
23     cout << "Enter the focal lengths, in mm, of " << LIMIT << " eyepieces: n";
24     for (int i = 0; i < LIMIT; i++)
25     {
26         cout << "Enter #" << i + 1 << ": ";
27         cin >> eps[i];
28     }
29     file_it(fout, objective, eps, LIMIT);       //将数据写入文件
30     file_it(cout, objective, eps, LIMIT);       //将同样的信息以相同的格式显示到屏幕上
31     cout << "Donen";
32     return 0;
33 }
34 
35 void file_it(ostream &os, double fo, const double fe[], int n)
36 {
37     ios_base::fmtflags initial;   //ios_base::fmtflags是储存这种信息所需的数据类型名称,initial存储调用file_it()之前的格式化设置
38     //setf()方法能够设置各种格式化状态
39     initial = os.setf(ios_base::fixed);    //set(ios_base::fixed)将对象置于使用定点表示法的模式
40     os.precision(0);                       //指定显示多少位小数(假定对象处于定点模式下)
41     os << "Focal length of objective: " << fo << " mmn";
42     os.setf(ios::showpoint);               //将对象置于显示小数点的模式,即使小数部分为零
43     os.precision(1);
44     os.width(12);
45     os << "f.l. eyepiece";
46     os.width(12);
47     os << "magnification" << endl;
48     for (int i = 0; i < n; i++)
49     {
50         os.width(12);
51         os << fe[i];
52         os.width(15);
53         os << int(fo / fe[i] + 0.5) << endl;
54     }
55     os.setf(initial);       //使用initial作为参数来调用setf(),将返回调用file_it()之前有效的所有格式化设置
56 }

[C++ Primer Plus] 第8章、函数探幽——(一)程序清单

[C++ Primer Plus] 第8章、函数探幽——(一)程序清单

 

 

 

以下是一些常见的控制函数的: 
dec 置基数为10 相当于"%d" 
hex 置基数为16 相当于"%X" 
oct 置基数为8 相当于"%o" 
setfill(c) 设填充字符为c 
setprecision(n) 设显示小数精度为n位 
setw(n) 设域宽为n个字符

setioflags(ios::fixed) 固定的浮点显示 
setioflags(ios::scientific) 指数表示 
setiosflags(ios::left) 左对齐 
setiosflags(ios::right) 右对齐 
setiosflags(ios::skipws 忽略前导空白 
setiosflags(ios::uppercase) 16进制数大写输出 
setiosflags(ios::lowercase) 16进制小写输出 
setiosflags(ios::showpoint) 强制显示小数点 
setiosflags(ios::showpos) 强制显示符号

8.3 默认参数

默认参数指的是当函数调用中省略了实参时自动使用的一个值。

注意:只有函数原型指定了默认值,函数定义与没有默认参数时完全相同。

 

 1 #include <iostream>
 2 using namespace std;
 3 const int ArzSize = 80;
 4 char *left(const char *str, int n = 1);
 5 
 6 int main()
 7 {
 8     char sample[ArzSize];
 9     cout << "Enter a string: n";
10     cin.get(sample, ArzSize);
11     char *ps = left(sample, 4);
12     cout << ps << endl;         //如果给cout提供一个指针,它将打印地址,但如果这个指针类型是char *,则cout将显示指向的字符串;若要显示地址,则应cout<<(int *)ps;如果couot<<*ps,则只会显示字符串的第一个字符
13     delete[]ps;
14     ps = left(sample);
15     cout << ps << endl;
16     delete[]ps;
17     return 0;
18 
19 }
20 
21 char *left(const char *str, int n)         //内部使用了new没有delete,所以main函数调用此方法后一定要记得delete
22 {
23     if (n < 0)
24         n = 0;
25     char *p = new char[n + 1];         //new和delete成对出现
26     int i;
27     for (i = 0; i < n && str[i]; i++)
28     {
29         p[i] = str[i];
30     }
31     while(i<=n)
32         p[i++] = '';
33     return p;
34 }

[C++ Primer Plus] 第8章、函数探幽——(一)程序清单

 

8.4 函数重载

默认参数让你能够使用不同数目的参数调用同一个函数。而函数多态(函数重载)让你能够使用多个同名的函数,“多态”指的是有多种形式,因此函数多态允许函数可以有多种形式。

C++允许定义名称相同的函数,条件是它们的特征标不同。函数的参数列表(也称为函数特征标):参数数目、参数类型、排列顺序。如果参数数目和/或参数类型不同,则特征标也不同。

 1 #include <iostream>
 2 using namespace std;
 3 
 4 unsigned long left(unsigned long num, unsigned ct);
 5 char * left(const char *str, int n = 1);
 6 
 7 int main()
 8 {
 9     char *trip = "Hawaii!!";
10     unsigned long n = 12345678;
11     int i;
12     char *temp;
13 
14     for (i = 1; i < 10;i++)
15     {
16         cout << left(n, i) << endl;
17         temp = left(trip, i);
18         cout << temp << endl;
19         delete []temp;              //此处delete
20     }
21     retuen 0;22     system("pause");         //这里写反了,stystem应该在return 0前面
23 }
24 
25 unsigned long left(unsigned long num, unsigned ct)
26 {
27     unsigned digits = 1;
28     unsigned long n = num;
29     
30     if (ct == 0 || num == 0)
31         return 0;
32     while (n /= 10)
33     {
34         digits++;
35     }
36     if (digits > ct)
37     {
38         ct = digits - ct;
39         while (ct--)
40             num /= 10;
41         return num;
42     }
43     else
44         return num;
45 }
46 
47 char * left(const char *str, int n)        //内部使用了new没有delete,所以main调用后一定要记得delete
48 {
49     if (n < 0)
50         n = 0; 
51     char *p = new char[n + 1];          //new和delete成对出现
52     int i;
53     for (i = 0; i < n && str[i];i++)
54     {
55         p[i] = str[i];
56     }
57     while (i <= n)
58         p[i++] = '';
59     return p;
60 }

[C++ Primer Plus] 第8章、函数探幽——(一)程序清单

 

 8.5 函数模板

函数模板是通用的函数描述,也就是说,它们使用泛型来定义函数,其中的泛型可用具体的类型(如int或double)替换。

如果需要多个将同一种算法用于不同类型的函数,请使用模板。

 1 #include <iostream>
 2 using namespace std;
 3 
 4 template<typename T>    //函数模板
 5 void Swap(T &a, T &b);    //不能用swap函数名,用户自己定义的swap()和STL库定义的函数重装冲突
 6 
 7 int main()
 8 {
 9     int i = 10, j = 20;
10     cout << "i,j= " << i << "," << j << endl;
11     Swap(i, j);
12     cout << "Now i,j= " << i << "," << j << endl;
13 
14     double x = 24.5, y = 81.7;
15     cout << "x,y= " << x << "," << y << endl;
16     Swap(x, y);
17     cout << "Now x,y= " << x << "," << y << endl;
18 
19     system("pause");
20     return 0;
21 }
22 
23 template<typename T>      //要记得写在这里
24 void Swap(T &a, T &b)
25 {
26     T temp;
27     temp = a;
28     a = b;
29     b = temp;
30 }

[C++ Primer Plus] 第8章、函数探幽——(一)程序清单

8.5.1 重载的模板

 1 #include <iostream>
 2 using namespace std;
 3 
 4 template<typename T>    //函数模板
 5 void Swap(T &a, T &b);    //不能用swap函数名,用户自己定义的swap()和STL库定义的函数重装冲突
 6 
 7 template<class T>       //模板的另一种表示方式
 8 void Swap(T *a, T *b, int n);
 9 
10 void show(int a[]);
11 const int Lim = 8;
12 
13 int main()
14 {
15     int i = 10, j = 20;
16     cout << "i,j= " << i << "," << j << endl;
17     Swap(i, j);
18     cout << "Now i,j= " << i << "," << j << endl;
19 
20     int d1[Lim] = { 0,7,0,4,1,7,7,6 };
21     int d2[Lim] = { 0,7,2,0,1,9,6,9 };
22     cout << "Original arrays: " << endl;
23     show(d1);
24     show(d2);
25     Swap(d1, d2, Lim);
26     cout << "Swap arrays: " << endl;
27     show(d1);
28     show(d2);
29 
30     system("pause");
31     return 0;
32 }
33 
34 template<class T>
35 void Swap(T &a, T &b)
36 {
37     T temp;
38     temp = a;
39     a = b;
40     b = temp;
41 }
42 
43 template<typename T>
44 void Swap(T *a, T *b, int n)
45 {
46     T temp;
47     for (int i = 0; i < n; i++)
48     {
49         temp = a[i];
50         a[i] = b[i];
51         b[i] = temp;
52     }
53 }
54 
55 void show(int a[])
56 {
57     cout << a[0] << a[1] << "/";
58     cout << a[2] << a[3] << "/";
59     for (int i = 4; i < Lim; i++)
60     {
61         cout << a[i];
62     }
63     cout << endl;
64 }

[C++ Primer Plus] 第8章、函数探幽——(一)程序清单

 8.5.3 显式具体化

需要显式具体化的情况:

假设定义了如下结构:

struct job
{
char name[40];
double salary;
int floor;
};

假设希望能交换两个这种结构的内容,原来的模板使用下面的代码来完成交换:

temp = a;
a = b;
b = temp;

但是如果只想交换salary和floor成员,而不想交换name成员,则需要使用不同的代码,但Swap()的参数将保持不变,因此无法使用模板重载来提供其他的代码,这样就有了显示具体化。

可以提供一个具体化函数定义,称为显式具体化,其中包含所需代码, 当编译器找到与函数调用匹配的具体化定义时,将使用该定义,而不在寻找模板。

  • 对于给定的函数名,可以有非模板函数、模板函数和显式具体化模板函数以及它们的重载版本。
  • 显式具体化的原型和定义应以template<>打头,并通过名称来指出类型。
  • 具体化优先于常规模板,而非模板函数优先于具体化和常规模板。
 1 #include <iostream>
 2 using namespace std;
 3 
 4 template<typename T>    
 5 void Swap(T &a, T &b);    
 6 
 7 struct job
 8 {
 9     char name[40];
10     double salary;
11     int floor;
12 };
13 
14 template<>void Swap<job>(job &j1, job &j2);
15 void show(job &j);
16 
17 int main()
18 {
19     cout.precision(2);      //指定显示多少位小数(假定处于定点模式下):看前面有没有cout<<fixed,如果没有的话, 是代表2位有效数字, 不是2位小数
20     cout.setf(ios::fixed, ios::floatfield);      //ios::fixed设置为定点输出格式,floatfield设置输出时按浮点格式,小数点后有6位数字
21     int i = 10, j = 20;
22     cout << "i,j= " << i << "," << j << endl;
23     Swap(i, j);
24     cout << "Now i,j= " << i << "," << j << endl;
25 
26     job sue = { "S Y", 73000.60, 7 };
27     job sid = { "S T", 78060.72, 9 };
28     cout << "Before job swapping: " << endl;
29     show(sue);
30     show(sid);
31     Swap(sue, sid);
32     cout << "After job swapping: " << endl;
33     show(sue);
34     show(sid);
35     system("pause");
36     return 0;
37 }
38 
39 //模板:交换a、b值
40 template <typename T>
41 void Swap(T &a, T &b) {
42     T temp = a;
43     a = b;
44     b = temp;
45 }
46 
47 //显示具体化:交换结构体内部成员值
48 template<>void Swap<job>(job &j1, job &j2)
49 {
50     double t1;
51     int t2;
52     t1 = j1.salary;
53     j1.salary = j2.salary;
54     j2.salary = t1;
55 
56     t2 = j1.floor;
57     j1.floor = j2.floor;
58     j2.floor = t2;
59 }
60 
61 void show(job &j)     //引用
62 {
63     cout << j.name << ":$" << j.salary << " on floor " << j.floor << endl;
64 }

[C++ Primer Plus] 第8章、函数探幽——(一)程序清单

 8.5.4 实例化和具体化

隐式实例化

显示实例化

显示具体化

8.5.5 编译器选择使用哪个函数版本

重载解析:对于函数重载、函数模板和函数模板重载,C++需要一个定义良好的策略,来决定为函数调用使用哪一个函数定义,尤其是有多个参数时。

 1 #include <iostream>
 2 using namespace std;
 3 
 4 template<typename T>       //template A
 5 void showarray(T arr[], int n);    
 6 
 7 template<typename T>       //template B
 8 void showarray(T *arr[], int n);
 9 
10 struct debts
11 {
12     char name[50];
13     double amount;
14 };
15 
16 int main()
17 {
18     int things[6] = { 13,31,103,301,310,130 };
19     struct debts mr_E[3]=
20     {
21         {"I W",2400.0},
22         {"U F",1300.0},
23         {"I S",1800.0}
24     };
25     double *pd[3];         //指针数组
26     for (int i = 0; i < 3; i++)
27     {
28         pd[i] = &mr_E[i].amount;
29     }
30     cout << "Listen:" << endl;
31     showarray(things, 6);
32     cout << "Listen debts:" << endl;
33     showarray(pd, 3);
34 
35     system("pause");
36     return 0;
37 }
38 
39 template<typename T>       //template A
40 void showarray(T arr[], int n)
41 {
42     cout << "template A" << endl;
43     for (int i = 0; i < n; i++)
44         cout << arr[i] << ' ';
45     cout << endl;
46 }
47 
48 template<typename T>       //template B
49 void showarray(T *arr[], int n)
50 {
51     cout << "template B" << endl;
52     for (int i = 0; i < n; i++)
53         cout << *arr[i] << ' ';
54     cout << endl;
55 }

[C++ Primer Plus] 第8章、函数探幽——(一)程序清单

 创建自定义选择

 1 #include <iostream>
 2 using namespace std;
 3 
 4 //返回小值
 5 template<class T>
 6 T lesser(T a, T b)
 7 {
 8     cout << "B";
 9     return a < b ? a : b;
10 }
11 
12 //先取绝对值,再返回绝对值中的小值
13 int lesser(int a, int b)
14 {
15     cout << "A";
16     a = a < 0 ? -a : a;
17     b = b < 0 ? -b : b;
18     return a < b ? a : b;
19 }
20 
21 int main()
22 {
23     int m = 20;
24     int n = -30;
25     double x = 15.5;
26     double y = 25.9;
27     cout << lesser(m, n) << endl;    //调用函数
28     cout << lesser(x, y) << endl;    //调用模板函数
29     cout << lesser<>(m, n) << endl;   //<>表示调用模板函数
30     cout << lesser<int>(x, y) << endl;   //<int>表示显示实例化,强转x,y的值
31 
32     system("pause");
33     return 0;
34 }

[C++ Primer Plus] 第8章、函数探幽——(一)程序清单

原文链接: https://www.cnblogs.com/Fionaaa/p/12391931.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    [C++ Primer Plus] 第8章、函数探幽——(一)程序清单

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/339829

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午12:18
下一篇 2023年3月2日 上午12:18

相关推荐