C++Primer Plus笔记——第八章 函数探幽及课后习题答案

目录

 

本章小结

程序清单

8.1  内联函数

8.2  创建引用变量

8.3  引用变量

8.4  引用作为函数参数

8.5  引用参数的特点

8.6   结构引用作为函数参数

8.7  程序崩溃

8.8  对象 继承和引用

8.9  默认参数

8.10  函数重载

8.11  函数模板

8.12  重载的模板

8.13  显式具体化

8.14  部分排序规则

8.15  自己选择

课后编程习题答案


本章小结


        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 &parameter
#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;
}

猜你喜欢

转载自blog.csdn.net/yukinoai/article/details/81449478