C++ Primer Plus 第八章知识点简化
1. 缺省值
归纳点:
- 缺省值的使用;
#include <iostream>
using namespace std;
const int ArSize = 80;
char* left(const char * str, int n=1); // 只用在该处写上默认值
int main(){
char sample[ArSize];
cout << "Enter a string:\n";
cin.get(sample, ArSize);
char* ps = left(sample, 4);
cout << ps << endl;
delete[] ps; // free old string
ps = left(sample);
cout << ps << endl;
delete[] ps; // free new string
return 0;
}
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;
}
输出:
Enter a string:
hello world
hell
h
笔记:
注意点:
- 必须从右向左来添加缺省值;
int fun(double a, float b, int c=0);
;- 函数定义与声明只用在声明处写上默认值,否则重定义(若没有声明就在定义处写上)。
2. 重载
归纳点:
- 重载的概念;
- 重载的注意点;
– 数据转换
– const的问题
函数重载即函数多态,使得能够使用多个同名的函数,他们之间怎么区分呢?靠的是形参,也就是形参数目以及类型,要是全相同就不能,例如void fun(int a, float b)
和double fun(int a, float b)
这两者只有返回值类型不一样,形参全一样,这样程序报错。
重载有时会将数据进行 强制转换,这种情况发生在唯一原型上。看下面的程序可知print(year, 10)
只和 void print(double, int)
相匹配,若加上另一个函数 void print(float, int)
,那么此时就不是唯一原型了,程序报错。
#include<iostream>
#include<string>
using namespace std;
void print(int, int);
void print(string, int);
int main(){
double year = 100.1;
print(year, 10);
return 0;
}
void print(int a, int b) {
cout << a << b << endl;
}
void print(string a, int b) {
cout << a;
}
输出:
10010
笔记:
重载里面 void fun(const string a);
和 void fun(string a);
可以同时存在,这时 const
常量会给到前者,非const
就会给到后者。那么此时就有问题了:
- 若只有后者,现在我有一个
const string a;
,这时会报错吗?
答案是不会,因为非const
值是可以赋给const
变量的;
- 若只有前者,现在我有一个
string a;
,这时会报错吗?
这时就会报错,非const
值赋给const
变量是合法的,反之则不行。
3. 模板
归纳点:
- 模板的概念;
- 显示具体化
- 显示实例化
- 完全匹配和最佳匹配
函数模板即泛型,假如有个函数是将两个int值交换,这时候要交换两个double值,且不损失地进行交换怎么办?这里说到的不损失就是不走刚才两个int交换的函数,因为强制转换会有损失,那就只能再重写一个double值交换的函数,具体操作就是复制刚才函数,将int改成double,是不是程序冗余费时还容易出错?这时候泛型起到作用。
#include<iostream>
using namespace std;
template <typename T> // or template <class` T>
void Swap(T& a, T& b);
int main(){
int i = 10;
int j = 20;
cout << "i, j = " << i << ", " << j << ".\n";
cout << "Using compiler-generated int swapper:\n";
Swap(i, j); // generates void Swap(int&, int&)
cout << "Now i, j = " << i << ", " << j << ".\n" << endl;
double x = 24.5;
double y = 81.7;
cout << "x, y = " << x << ", " << y << ".\n";
cout << "Using compiler-generated double swapper:\n";
Swap(x, y); // generates void Swap(double&, double&)
cout << "Now x, y = " << x << ", " << y << ".\n";
return 0;
}
template <typename T> // 别忘了声明和定义都要加这么一句
void Swap(T &a, T &b){
T temp = a;
a = b;
b = temp;
}
输出:
i, j = 10, 20.
Using compiler-generated int swapper:
Now i, j = 20, 10.
x, y = 24.5, 81.7.
Using compiler-generated double swapper:
Now x, y = 81.7, 24.5.
笔记:
上面简要介绍模板用法,但有个问题可以来思考下:刚才那个换数据类型由int --> double 用刚才模板即可,交换的话直接用个temp作为中间值来实现,但数据类型如果是结构体,交换的是其中的成员该怎么办,可以用刚才那个函数吗?显然不可以,但又是实现交换,和刚才一样功能,就这个struct是个特殊的,单独为struct写一个?有更快的办法吗?
方法是有的,还是用模板,但需要 显示具体化,如下所示:
#include <iostream>
using namespace std;
struct job {
char name[40];
double salary;
int floor;
};
template <typename T>
void Swap(T &a, T &b);
// explicit specialization
template <> void Swap<job>(job &j1, job &j2); // or template <> void Swap(job &j1, job &j2);
void Show(job &j);
int main() {
cout.precision(2);
cout.setf(ios::fixed, ios::floatfield);
int i = 10, j = 20;
cout << "i, j = " << i << ", " << j << ".\n";
cout << "Using compiler-generated int swapper:\n";
Swap(i, j); // generates void Swap(int &, int &)
cout << "Now i, j = " << i << ", " << j << ".\n" << endl;
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 << "\nAfter job swapping:\n";
Show(sue);
Show(sidney);
return 0;
}
template <typename T>
void Swap(T &a, T &b) { // 通用版本
T temp;
temp = a;
a = b;
b = temp;
}
template <> void Swap<job>(job &j1, job &j2) { // 显示具体化版本
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) {
cout << j.name << ": $" << j.salary << " on floor " << j.floor << endl;
}
输出:
i, j = 10, 20.
Using compiler-generated int swapper:
Now i, j = 20, 10.
Before job swapping:
Susan Yaffee: $73000.60 on floor 7
Sidney Taffee: $78060.72 on floor 9
After job swapping:
Susan Yaffee: $78060.72 on floor 9
Sidney Taffee: $73000.60 on floor 7
笔记:
Reference:
- 《C++ Primer Plus》第六版 Stephen Prata 著