第七章 函数(要注意的几点)
1、一旦函数执行结束,这些在函数内的局部变量的值也会没有。
2、指针形参: 如果函数形参是非const类型的指针,则函数课通过指针实现赋值,修改指针所指向对象的值;
如: void reset(int *ip);
{
*ip= 0; 改变指针指向对象的值
Ip = 0; 改变形参的值,实参不变。
}
如需要保护指针指向的值,则形参需要定义为指向const对象的指针:
Void use_ptr(const int *p)
{
Use_ptr 只能读*p,不能改变*p的值,即指向对象的值。
}
(注意:可以将指向const对象的指针初始化为指向非const对象,但不可以让指向非const对象的指针指向const对象)
3、const形参: 如果该函数使用非引用的非const形参,则既可给该函数传递const实参,也可以传递非const的实参。
如果将形参定义为为引用的const类型 : void fcn(const int i){ } i只能读不能改变其。由于实参仍然是以副本的形式传递,因此传递给fcn的既可以是const对象也可以是非const对象。
4、复制实参的局限性:
·当需要在函数中修改实参的值时;
·当需要以大型对象作为实参传递时;
·没有办法实现对象的复制时。
5、引用形参: 函数:voud swap (int &v1,int &v2) { } 与所有引用一样,引用形参直接关联到其所绑定的对象。Swap( I , j )此时的,形参v1只是对象i的另一个名字,v2是对象j的另一个名字。
(注意:在C++中,使用引用形参更安全和更自然)
6、利用const引用避免复制: bool isShorter(const string &s1,const string &s2){ } 每一个形参都是const string 类型的引用,因为形参是引用,所以不复制实参。又因为形参是const引用,所以isShorter函数不能使用该引用来修改实参。
(注意:如果使用引用形参的唯一目的是避免复制实参,则应该将形参定义为const引用。另外,将不需要修改的引用形参定义为const引用。普通的非const引用形参在使用时不太灵活。这样的形参既不能用const对象初始化,也不能用字面值或产生右值的表达式实参初始化。)
7、传递指向指针的引用: void ptrswap(int *&v1, int *&v2){ } 形参的定义应该从右至左理解:v1是一个引用,与指向int 型对象的指针关联,也就是说,v1只是传递进prtswap函数的任意指针的别名。
8、数组形参:因为数组会被自动转化为指针,所以处理数组的函数通常通过操纵指向数组中的元素的指针来处理数组。
三种方式指定数组形参:
Void printValue(int *) {}
Void printValue(int []) {}
Void printValue(int [10] ) { }
(注意:将数组形参直接定义为指针要比使用数组语法定义更好。这表示,函数操纵的是指向数组元素的指针,而不是数组本身。另外,当编译器检查数组形参关联的实参时,它只会检查实参是不是指针、指针的类型和数组元素的类型是否匹配,而不会检查数组的长度。)
9、不要返回局部对象的引用:
Const string &manip (const string &s)
{
String ret = s;
Return ret ;
}
当函数执行完毕,字符串ret占用的存储空间被释放,函数返回值指向对于这个程序来说不再有效的内存空间。返回引用安全的一个好方法:自问:这个引用指向那个在此之前存在的对象?
10、static局部对象:确保不迟于在程序执行流程第一次经过该对象的定义语句时进行初始化,这种对象一旦被初始化,在出程序结束前都不会被撤销。
11、内联函数:在函数返回类型前加上关键字inline就可以将shorterString函数指定为内联函数: inline const string &shorterString(const string &s1,const string &s2)
(注意:一般来说,内联机制适用于优化小的,只有几行的而且经常被调用的函数。大多数编译器都不支持递归函数的内联。内联函数应该在头文件中定义。)
12、类的成员函数:类的所有成员都必须在类定义的花括号里面声明,既可以在类的定义内,也可以在类的定义外定义。(类的成员函数可以访问该类的private成员)
13、构造函数:是特殊的成员函数,与其他成员函数不同,构造函数和类同名,而且没有返回类型。(一个类可以有多个构造函数,每个构造函数必须有与其他构造函数不同数目或类型的形参)
构造函数的定义:如 sales_item(形参表):units_sold(0) , revenue(0.0) { 函数体 }
通常构造函数会作为类的接口的一部分,如果将构造函数定义为private,则不能定义类sales_item 的对象,这样这个类也就没有什么用了。在上面的语句中说明正在定义类salse_item 的构造函数,这个构造函数的形参表和函数体都为空。在冒号和花括号之间的代码称为构造函数初始化列表,每个成员后面是括在圆括号中的初始值,多个成员的初始化用逗号分隔。
14、重载函数:出现在相同作用域的两个函数,如果具有相同名字而形参表不同,就称为重载函数。
Record lookup(const account&);
Record lookup(const phone&);
Record lookup(const name&);
这里三个函数恭喜同一个函数名,但却是三个不同的函数。编译器会根据所传的实参类型来判断调用的是哪个函数。(任何程序都仅有一个main函数,main函数不能重载)
函数重载和重复声明的区别:如果两个函数声明的返回类型和形参表完全匹配,则将第二个函数声明视为第一个的重复声明。如果两个函数的形参表完全相同,返回类型不同,则第二个声明是错误的:
Record lookup(const account&);
bool lookup(const account&); 出错!
(函数不能仅仅基于不同的返回类型而实现重载)
注意:形参与const形参的等价性进适用于肺引用形参。有const引用形参的函数与有非const引用形参的函数是不同的。类似的,如果函数带有指向const类型的指针形参,则与带有指向相同类型的非const对象指针形参函数不同。
15、指向函数的指针:是指指向函数而非指向对象的指针。
如: bool (*pf)(const string &, const string &);(*pf两侧的括号不能省)
用typedef简化函数指针的定义: typedef bool (*cmpFcn)(const string &,const string &);该定义表示cmpFcn是一种指向函数的指针类型的名字。直接引用函数名的呢功效与在函数名上应用取地址操作符:
Bool lengthCompare(const string &, const string &);
cmpFcn pf1 = lengthCompare ;
cmpFcn pf2= &lengthCompare ;
函数指针只能通过同类型的函数或函数指针或0常量表达式进行初始化:
cmpFcn pf1 = 0 ;
cmpFcn pf1 = pf1;
cmpFcn pf1 = lengthCompare ;
pf2 = lengthCompare ;
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
前两天都没有写日志,是因为有一天外出了,昨天在看书,笔记来不及写了,今天就补上昨天的笔记吧。在第七章函数里,还是有很多很多要注意的地方,比如函数返回引用那一点,我就不是很明白,感觉书上没有写对,上网百度一下,很多也都是直接抄书上的。看来具体问题还是要请教一下师兄或者老师了。不过早上师兄都没来,今天之内一定会问清楚,弄明白的!