1. 一个函数的定义也就是一个给出了函数体的函数声明
2. inline描述符并不影响函数的语义
3. 如果一局部变量被声明为static,那么将只有一个静态分配的对象,它被用于在该函数的所有调用中表示这个变量。这个对象将只在执行线程第一次到达它的定义时初始化。
4. 将指针参数声明为const,也就是告知读者,函数将不修改由这个参数所指的对象
5. 文字量,常量,和需要转换的参数都可以传递给const&参数,但不能传递给非const的引用参数
6. 数组与其他类型不同,数组不会按值的方式传递。对于被调用函数而言,数组参数的大小是不可利用的。
7. 将同一个名字用于在不同类型上操作的函数的情况成为重载。当一个函数f被调用时,编译器就必须弄清楚究竟应该调用具有名字f的哪一个函数。为了完成这项工作,它需要将实际参数的类型与所有名字为f的函数的形式参数的类型相比较。基本想法是去调用其中的那个在参数上匹配得最好的函数,如果不存在匹配的最好的函数,就给出一个编译错误。
8. 为了尽可能接近最合理的观念,需要按顺序检查下面一系列的匹配准则:准确匹配 -> 利用提升的匹配 -> 利用标准转换 -> 利用用户定义转换 -> 利用在函数声明中的省略号
9. 重载解析中将不考虑返回类型
10. 在不同的非名字空间作用域里声明的函数不算是重载
11. 如果希望重载能够跨越作用域或名字空间作用域,那么可以利用“使用声明”或者“使用指令”
12. 一些c++新手会被编译器报告出的歧义性错误弄得急躁起来。更有经验的程序员则欣赏这种错误信息,将它们看作是很有用的关于设计错误的指示器。
13. 默认参数的类型将在函数声明时检查,在调用时求值。在同一个作用域中随后的声明里,默认参数都不能重复或者改变。
14. 声明这种函数的方式是在参数表的最后使用省略号结束,省略号标示“还可能有另外一些参数”。这样的函数必须依赖于一些编译时无法使用的信息区解释它的参数表。
15. 使用整数0作为结束符可能产生不可移植的问题:在某些实现中,整数0和空指针的表示形式可能不同。
16. 从一个使用过va_start()的函数中退出之前,必须调用一次va_end()。这是因为va_start()可能以某种方式修改了堆栈,这种修改可能导致返回无法完成,va_end()能将有关的修改复原。
17. 对于一个函数只能做两件事:调用它,或者取得它的地址
练习题:9, 10, 15
9.
void SimpleEncrypt() {
string key;
cout << "Please input keys used to encrypt: " << endl;
getline(cin, key);
if (key.size() == 0) {
cout << "Key is empty, the input string will not be encrypted!" << endl;
}
cout << "Please input string to be encrypted: " << endl;
string str, str_encrypted, str_decrypted;
getline(cin, str);
if (key.size() > 0) {
int keyIndex = 0;
for (int i=0; i<str.size(); i++) {
str_encrypted.push_back(str[i] ^ key[keyIndex]);
keyIndex = (++keyIndex) % key.size();
}
}
else {
str_encrypted = str;
}
if (key.size() > 0) {
int keyIndex = 0;
for (int i=0; i<str_encrypted.size(); i++) {
str_decrypted.push_back(str_encrypted[i] ^ key[keyIndex]);
keyIndex = (++keyIndex) % key.size();
}
}
else {
str_decrypted = str_encrypted;
}
cout << "Encrypted key: " << str_encrypted << endl;
cout << "Decrypted key: " << str_decrypted << endl;
};