目录
本章小结
C++扩展了C语言的函数功能。通过将inline关键字用于函数定义,并在首次调用该函数前提供其函数定义,可以使得C++编译器将该函数视为内联函数。也就是说,编译器不是让程序跳到独立的代码段,以执行函数,而是用相应的代码替换函数调用。只有在函数很短时才能采用内联方式。
引用变量是一种伪装指针,它允许为变量创建别名(另一个名称)。引用变量主要被用作处理结构和类对象的函数的参数。通常,被声明为特定类型引用的标识符只能指向这种类型的数据;然而,如果一个类是从另一个类派生派生出来的,则基类引用可以指向派生类对象。
C++原型让您能够定义参数的默认值。如果函数调用省略了相应的参数,则程序将使用默认值;如果函数调用提供了参数值,则程序将使用这个值(而不是默认值)。只能在参数列表中从右到左提供默认参数。因此,如果为某个参数提供了默认值,则必须为该参数右边所有的参数提供默认值。
函数的特征是其参数列表。程序员可以定义两个同名函数,只要其特征标不同。这被称为函数多态或函数重载,通常,通过重载函数来为不同的数据类型提供相同的服务。
函数模板自动完成重载函数的过程。只需使用泛型和具体算法来定义函数,编译器将为程序中使用的特定参数类型生成正确的函数定义。
程序清单
8.1 内联函数
//inline.cpp -- using an inline function
#include "stdafx.h"
#include<iostream>
//inline double function definition
inline double square(double x)
{
return x * x;
}
int main()
{
using namespace std;
double a, b;
double c = 13.0;
a = square(5.0);
b = square(4.5 + 7.5);
cout << "a = " << a << " , b = " << b << "\n";
cout << "c = " << c;
cout << ", c squared = " << square(c++) << "\n";
cout << "Now c = " << c << "\n";
return 0;
}
8.2 创建引用变量
//firstref.cpp -- defining and using a reference
#include "stdafx.h"
#include<iostream>
int main()
{
using namespace std;
int rats = 101;
int & rodents = rats;//rodents is a reference
cout << "rats = " << rats;
cout << ", rodents = " << rodents << endl;
rodents++;
cout << "rats = " << rats;
cout << ", rodents = " << rodents << endl;
//some implementations require type casting the following addresses to type unsigned
cout << "rats address = " << &rats;
cout << ", rodents address = " << &rodents << endl;
return 0;
}
8.3 引用变量
//secref.cpp -- defining and using a reference
#include "stdafx.h"
#include<iostream>
int main()
{
using namespace std;
int rats = 101;
int & rodents = rats;
cout << "rats = " << rats << ", rodents = " << rodents << endl;
cout << "rats address = " << &rats << ", rodents address = " << &rodents << endl;
int bunnies = 50;
rodents = bunnies;
cout << "bunnies = " << bunnies << ", rats = " << rats << "rodents = " << rodents << endl;
cout << "bunnies address = " << &bunnies << ", rodents address = " << &rodents << endl;
return 0;
}
8.4 引用作为函数参数
//swaps.cpp -- swapping with reference and with pointers
#include "stdafx.h"
#include<iostream>
void swapr(int & a, int & b);//a,b are aliases for ints
void swapp(int * p, int * q);//p,q are addresses of ints
void swapv(int a, int b);//a,b are new variables
int main()
{
using namespace std;
int wallet1 = 300;
int wallet2 = 350;
cout << "wallet1 = $" << wallet1;
cout << " wallet2 = $" << wallet2 << endl;
cout << "Using references to swap contents:\n";
swapr(wallet1, wallet2); //pass variables
cout << "wallet1 = $" << wallet1;
cout << " wallet2 = $" << wallet2 << endl;
cout << "Using pointers to swap contents:\n";
swapp(& wallet1, & wallet2); //pass addresses of variables
cout << "wallet1 = $" << wallet1;
cout << " wallet2 = $" << wallet2 << endl;
cout << "Trying to use passing by value:\n";
swapv(wallet1, wallet2); //pass values of variables
cout << "wallet1 = $" << wallet1;
cout << " wallet2 = $" << wallet2 << endl;
return 0;
}
void swapr(int & a, int & b) //use references
{
int temp;
temp = a; //use a, b for values of variables
a = b;
b = temp;
}
void swapp(int * p, int * q) //use pointers
{
int temp;
temp = *p; //use *p,*q for values of variables
*p = *q;
*q = temp;
}
void swapv(int a, int b) //try using values
{
int temp;
temp = a;//use a,b for values of variables
a = b;
b = temp;
}
8.5 引用参数的特点
//cubes.cpp -- regular and reference arguments
#include "stdafx.h"
#include<iostream>
double cube(double a);
double refcube(double &ra);
int main()
{
using namespace std;
double x = 3.0;
cout << cube(x);
cout << " = cube of " << x << endl;
cout << refcube(x);
cout << " = cube of " << x << endl;
return 0;
}
double cube(double a)
{
a *= a * a;
return a;
}
double refcube(double &ra)
{
ra *= ra * ra;
return ra;
}
8.6 结构引用作为函数参数
//strc_ref.cpp -- using structure references
#include "stdafx.h"
#include<iostream>
#include<string>
using namespace std;
struct free_throws
{
string name;
int made;
int attempts;
float percent;
};
void display(const free_throws & ft);
void set_pc(free_throws & ft);
free_throws & accumulate(free_throws & target, const free_throws & source);
int main()
{
//partial initialization - remaining members set to 0
free_throws one = { "Ifelsa Branch",13,14 };
free_throws two = { "Andor Knott", 10,16 };
free_throws three = { "Minnie Max", 7, 9 };
free_throws four = { "Whily Looper", 5, 9 };
free_throws five = { "Long Long", 6, 14 };
free_throws team = { "Throwgoods", 0, 0 };
//no initialization
free_throws dup;
set_pc(one);
display(one);
accumulate(team, one);
display(team);
//use return value as argument
display(accumulate(team, two));
accumulate(accumulate(team, three), four);
display(team);
//use return value in assignment
dup = accumulate(team, five);
cout << "Displaying team:\n";
display(team);
cout << "Displaying dup after assignment:\n";
display(dup);
set_pc(four);
//ill-advised assignment
accumulate(dup, five) = four;
cout << "Displaying dup afer ill-advise assignment:\n";
display(dup);
return 0;
}
void display(const free_throws & ft)
{
cout << "Name: " << ft.name << endl;
cout << " Made: " << ft.made << '\t';
cout << "Attempts: " << ft.attempts << '\t';
cout << "Percent: " << ft.percent << endl;
}
void set_pc(free_throws & ft)
{
if (ft.attempts != 0)
ft.percent = 100.0f*float(ft.made) / float(ft.attempts);
else
ft.percent = 0;
}
free_throws & accumulate(free_throws & target, const free_throws & source)
{
target.attempts += source.attempts;
target.made += source.made;
set_pc(target);
return target;
}
8.7 程序崩溃
8.8 对象 继承和引用
//filefunc.cpp -- function with ostream ¶meter
#include "stdafx.h"
#include<iostream>
#include<fstream>
#include<cstdlib>
using namespace std;
void file_it(ostream &os, double fo, const double fe[], int n);
const int LIMIT = 5;
int main()
{
ofstream fout;
const char *fn = "ep-data.txt";
fout.open(fn);
if (!fout.is_open())
{
cout << "Can't open " << fn << ". Bye.\n";
exit(EXIT_FAILURE);
}
double objective;
cout << "Enter the focal length of your telescope objective in mm: ";
cin >> objective;
double eps[LIMIT];
cout << "Enter the focal lengths,in mm,of " << LIMIT << " eyepieces:\n";
for (int i = 0; i < LIMIT; i++)
{
cout << "Eyepiece #" << i + 1 << ": ";
cin >> eps[i];
}
file_it(fout, objective, eps, LIMIT);
file_it(cout, objective, eps, LIMIT);
cout << "Done\n";
return 0;
}
void file_it(ostream &os, double fo, const double fe[], int n)
{
ios::fmtflags initial;
initial = os.setf(ios_base::fixed);//save initial formatting state
os.precision(0);
os << "Focal length of objective: " << fo << " mm\n";
os.setf(ios::showpoint);
os.precision(1);
os.width(12);
os << "f.1. eyepiece";
os.width(15);
os << "magnification" << endl;
for (int i = 0; i < n; i++)
{
os.width(12);
os << fe[i];
os.width(15);
os << int(fo / fe[i] + 0.5) << endl;
}
os.setf(initial);//restore initial formatting state
}
8.9 默认参数
//left.cpp -- string function with a default argument
#include "stdafx.h"
#include<iostream>
const int ArSize = 80;
char * left(const char*str, int n = 1);
int main()
{
using namespace std;
char sample[ArSize];
cout << "Enter a string:\n";
cin.get(sample, ArSize);
char *ps = left(sample, 4);
cout << ps << endl;
delete[] ps;
ps = left(sample);
cout << ps << endl;
delete[] ps;
return 0;
}
//This function returns a pointer to a new string consisting of the first n characters in the str string.
char * left(const char*str, int n)
{
if (n < 0)
n = 0;
char *p = new char[n + 1];
int i;
for (i = 0; i < n && str[i]; i++)
p[i] = str[i];//copy characters
while (i <= n)
p[i++] = '\0';
return p;
}
8.10 函数重载
//leftover.cpp -- overloading the left() function
#include "stdafx.h"
#include<iostream>
unsigned long left(unsigned long num, unsigned ct);
char * left(const char * str, int n = 1);
int main()
{
using namespace std;
const char * trip = "Hawaii!!";
unsigned long n = 12345678;
int i = 1;
char* temp;
for ( i = 1; i < 10; i++)
{
cout << left(n, i) << endl;
temp = left(trip, i);
cout << temp << endl;
delete[] temp;//point to temporary storage
}
return 0;
}
//This function returns the first ct digits of the number num.
unsigned long left(unsigned long num, unsigned ct)
{
unsigned digits = 1;
unsigned long n = num;
if (ct == 0 || num == 0)
return 0;
while (n /= 10)
digits++;
if (digits > ct)
{
ct = digits - ct;
while (ct--)
num /= 10;
return num;
}
else
return num;
}
//This function returns a pointer to a new string consisting of the first n characters in the str string
char * left(const char * str, int n)
{
if (n < 0)
n = 0;
char *p = new char[n + 1];
int i;
for (i = 0; i < n&&str[i]; i++)
p[i] = str[i];//copy characters
while (i <= n)
p[i++] = '\0';//set rest of string to '\0'
return p;
}
8.11 函数模板
//funtemp.cpp -- using a function template
#include "stdafx.h"
#include<iostream>
//function template prototype
template<typename T>//or class T
void Swap(T &a, T &b);
int main()
{
using namespace std;
int i = 10;
int j = 20;
cout << "i = " << i << ", j = " << j << ".\n";
cout << "Using compiler-generated int swapper:\n";
Swap(i, j);//generates void Swap(int &, int &)
cout << "Now i = " << i << ", j = " << j << ".\n";
double x = 24.5;
double y = 81.7;
cout << "x, = " << x << ", y =" << y << ".\n";
cout << "Using compiler-generated double swapper:\n";
Swap(x, y);//generates void Swap(double &, double &)
cout << "Now x = " << x << ", y = " << y << ".\n";
return 0;
}
//function template definition
template <typename T>
void Swap(T &a, T &b)
{
T temp;//temp a variable of type T
temp = a;
a = b;
b = temp;
}
8.12 重载的模板
//twotemps.cpp -- using overloaded template functions
#include "stdafx.h"
#include<iostream>
template<typename T>
void Swap(T &a, T &b);
template<typename T>
void Swap(T *a, T *b, int n);
void Show(int a[]);
const int Lim = 8;
int main()
{
using namespace std;
int i = 10, j = 20;
cout << "i = " << i << ", j = " << j << ".\n";
cout << "Using compiler-generated int swapper:\n";
Swap(i, j);
cout << "Now i = " << i << ", j = " << j << ".\n";
int d1[Lim] = { 0,7,0,4,1,7,7,6 };
int d2[Lim] = { 0,7,2,0,1,9,6,9 };
cout << "Original arrays: \n";
Show(d1);
Show(d2);
Swap(d1, d2, Lim);
cout << "Sawpped arrays:\n";
Show(d1);
Show(d2);
return 0;
}
template<typename T>
void Swap(T &a, T &b)
{
T temp;
temp = a;
a = b;
b = temp;
}
template<typename T>
void Swap(T a[], T b[], int n)
{
T temp;
for (int i = 0; i < n; i++)
{
temp = a[i];
a[i] = b[i];
b[i] = temp;
}
}
void Show(int a[])
{
using namespace std;
cout << a[0] << a[1] << "/" << a[2] << a[3] << "/";
for (int i = 4; i < Lim; i++)
cout << a[i];
cout << endl;
}
8.13 显式具体化
// twoswap.cpp -- specialization overrides a template
#include "stdafx.h"
#include<iostream>
template <typename T>
void Swap(T &a, T &b);
struct job
{
char name[40];
double salary;
int floor;
};
// explicit specialization 显式具体化
template<> void Swap<job>(job & j1, job & j2);
void Show(job & j);
int main()
{
using namespace std;
cout.precision(2);
cout.setf(ios::fixed, ios::floatfield);
int i = 10, j = 20;
cout << "i = " << i << ", j = " << j << ".\n";
cout << "Using compiler-generated int swapper: \n";
Swap(i, j); // generates void Swap(int &, int &)
cout << "Now i = " << i << ", j = " << j << ".\n";
job sue = { "Susan Yaffee", 73000.60, 7 };
job sidney = { "Sidney Taffee", 78060.72, 9 };
cout << "Before job swapping: \n";
Show(sue);
Show(sidney);
Swap(sue, sidney); // uses void Swap(job & , job &)
cout << "After job swapping: \n";
Show(sue);
Show(sidney);
return 0;
}
template <typename T>
void Swap(T &a, T &b) // general version
{
T temp;
temp = a;
a = b;
b = temp;
}
// swaps just the salary and floor fields of a job structure
template<> void Swap<job>(job &j1, job &j2) // specialization
{
double t1;
int t2;
t1 = j1.salary;
j1.salary = j2.salary;
j2.salary = t1;
t2 = j1.floor;
j1.floor = j2.floor;
j2.floor = t2;
}
void Show(job & j)
{
using namespace std;
cout << j.name << ": $" << j.salary << " on floor " << j.floor << endl;
}
8.14 部分排序规则
//tempover.cpp -- template overloading
#include "stdafx.h"
#include<iostream>
struct debts
{
char name[50];
double amount;
};
template <typename T>
void ShowArray(T arr[], int n);
template <typename T>
void ShowArray(T * arr[], int n);
int main()
{
using namespace std;
int things[6] = { 13,31,103,301,310,130 };
struct debts mr_E[3]
{
{"Ima Wolfe",2400.0},
{"Ura Foxe",1300.0},
{"Iby Stout",1800.0}
};
double * pd[3];
//set pointers to the amount members of the structures in mr_E
for (int i = 0; i < 3; i++)
pd[i] = &mr_E[i].amount;
cout << "Listing Mr.E's counts of things:\n";
//things is an array of int
ShowArray(things, 6);
cout << endl << "Listing Mr.E's debts:\n";
//pd is an array of pointers to double
ShowArray(pd, 3);//uses template B (more specialized)
return 0;
}
template <typename T>
void ShowArray(T arr[], int n)
{
using namespace std;
cout << "template A\n";
for (int i = 0; i < n; i++)
cout << arr[i] << ' ';
cout << endl;
}
template <typename T>
void ShowArray(T * arr[], int n)
{
using namespace std;
cout << "template B\n";
for (int i = 0; i < n; i++)
cout << *arr[i] << ' ';
cout << endl;
}
8.15 自己选择
//choices.cpp -- choosing a template
#include "stdafx.h"
#include<iostream>
template<class T>
T lesser(T a, T b)
{
return a < b ? a : b;
}
int lesser(int a, int b)
{
a = a < 0 ? -a : a;
b = b < 0 ? -b : b;
return a < b ? a : b;
}
int main()
{
using namespace std;
int m = 20;
int n = -30;
double x = 15.5;
double y = 25.9;
cout << lesser(m, n) << endl;
cout << lesser(x, y) << endl;
cout << lesser<>(m, n) << endl;
cout << lesser<int>(x, y) << endl;
return 0;
}
课后编程习题答案
//practice.cpp
//运行时删除或注释掉多余的部分
#include "stdafx.h"
#include<iostream>
#include<string>
#include<cctype>
#include<cstring>
//practice-1
void show(const char * ps, int n = 0);
int main()
{
using namespace std;
char * pstr = "Hello\n";
show(pstr);
int num;
cout << "Enter a number: ";
cin >> num;
show(pstr, num);
cout << "Done\n";
return 0;
}
void show(const char * ps, int n)
{
using namespace std;
int lim = n;
if (n == 0)
lim = 1;
for (int i = 0; i < lim; i++)
cout << ps;
}
//practice-2
using namespace std;
struct CandyBar {
string brand;
double weight;
int calories;
};
void function(CandyBar &, char * str = "Millennium Munch", double a = 2.85, int b = 350);
void show(const CandyBar &);
int main()
{
CandyBar x;
cout << "Please enter the brand: \n";
getline(cin, x.brand);
cout << "Please enter the weight: \n";
cin >> x.weight;
cout << "Please enter the colories: \n";
cin >> x.calories;
show(x);
function(x);
show(x);
return 0;
}
void show(const CandyBar &a)
{
cout << endl << a.brand << endl
<< a.weight << endl
<< a.calories << endl;
}
void function(CandyBar &r, char * str, double a, int b)
{
r.brand = str;
r.weight = a;
r.calories = b;
}
//practice-3
using namespace std;
void upper(string &);
int main()
{
string str;
cout << "Enter a string (q to quit): ";
getline(cin, str);
while (str != "q" && str != "Q")
{
upper(str);
cout << str << endl;
cout << "Next string (q to quit): ";
getline(cin, str);
}
cout << "Bye.\n";
return 0;
}
void upper(string & a)
{
for (int i = 0; i < a.size(); i++)
{
if (islower(a[i]))
a[i] = toupper(a[i]);
}
}
//practice-4
using namespace std;
struct stringy
{
char * str;
int ct;
};
void set(stringy &, char[]);
void show(const stringy &, int n = 1);
void show(const char[], int n = 1);
int main()
{
stringy beany;
char testing[] = "Reality isn't what it used to be.";
set(beany, testing);
show(beany);
show(beany, 2);
testing[0] = 'D';
testing[1] = 'u';
show(testing);
show(testing, 3);
show("Done!");
return 0;
}
void set(stringy & a, char b[])
{
a.str = b;
}
void show(const stringy &x, int n)
{
for (int i = n; i > 0; i--)
cout << x.str << endl;
}
void show(const char a[], int n)
{
for (int i = n; i > 0; i--)
cout << a << endl;
}
//practice-5
using namespace std;
const int Num = 5;
template <class AnyType>
AnyType max5(AnyType[]);
int main()
{
int a[Num] = { 1, 2, 3, 4, 5 };
double b[Num] = { 1.1, 2.2, 3.3, 4.4, 5.5 };
int maxi = max5(a);
double maxd = max5(b);
cout << "max in a[5]: " << maxi << endl
<< "max in b[5]: " << maxd << endl;
return 0;
}
template <class AnyType>
AnyType max5(AnyType ar[])
{
AnyType max = ar[0];
for (int i = 0; i < 5; i++)
{
if (max < ar[i])
max = ar[i];
}
return max;
}
//practice-6
using namespace std;
template <typename T>
T maxn(T[], int);
template <> const char* maxn<const char *>(const char *[], int);
int main()
{
int a[6] = { 1, 2, 3, 4, 5, 6 };
double b[4] = { 1.1, 2.2, 3.3, 4.4 };
int maxi = maxn(a, 6);
double maxd = maxn(b, 4);
const char * c[5] =
{
"a",
"bb",
"ccc",
"ddddd",
"eeee"
};
cout << "maxi: " << maxi << endl
<< "maxd: " << maxd << endl
<< "The max string of array is: " << maxn(c, 5) << endl;
return 0;
}
template <typename T>
T maxn(T ar[], int n)
{
T max = ar[0];
for (int i = 0; i < n; i++)
{
if (max < ar[i])
max = ar[i];
}
return max;
}
template <> const char* maxn<const char *>(const char * ar[], int n)
{
const char * maxs = ar[0];
for (int i = 1; i < n; i++)
{
if(strlen(maxs) < strlen(ar[i]))
maxs = ar[i];
}
return maxs;
}
//practice-7
template <typename T>
T SumArrray(T arr[], int n);
template <typename T>
T SumArrray(T * arr[], int n);
struct debts
{
char name[50];
double amount;
};
int main()
{
using namespace std;
int things[6] = { 13, 31, 103, 301, 310, 130 };
struct debts mr_E[3] =
{
{ "Ima Wolfe", 2400.0 },
{ "Ura Foxe", 1300.0 },
{ "Iby Stout", 1800.0 }
};
double * pd[3];
for (int i = 0; i < 3; i++)
pd[i] = &mr_E[i].amount;
cout << "Sum: Mr.E's counts of things: "
<< SumArrray(things, 6) << endl;
cout << "Sum: Mr.E's debts: "
<< SumArrray(pd, 3) << endl;
return 0;
}
template <typename T>
T SumArrray(T arr[], int n)
{
using namespace std;
T sum = 0;
cout << "template A\n";
for (int i = 0; i < n; i++)
sum += arr[i];
return sum;
}
template <typename T>
T SumArrray(T * arr[], int n)
{
using namespace std;
T sum = 0;
cout << "template B\n";
for (int i = 0; i < n; i++)
sum += *arr[i];
return sum;
}