C++基础知识(三)——函数

来源:互联网 发布:上海java培训 编辑:程序博客网 时间:2024/06/05 18:46

一、内联函数:
在使用内联函数前,要先明白普通函数是如何调用的:首先,调用前要先保存寄存器,并在返回时恢复(调用前为函数开辟内存空间,并在函数结
束时释放内存空间);其次,需要参数的复制(浪费时间);程序在调用时需要转向一个新位置执行,结束时再返回原来的位置,而内联函数,(通常)就是将它在程序中的每个调用点上“内联地”展开,避难了系统多余的开销;
注意:
1)内联函数使用于只有优化小的、只有几行代码的而且经常被调用的函数;
2)大多数的编译器不支持递归函数的内联;
3)内联标识符对编译器来说只是一个建议,而不是强制性的,编译器可以选择忽略这个建议

4)内联函数应该在头文件中定义,这点不同于其他函数(内联函数小,而且(通常)要经常被调用,便于函数的维护)
5)在头文件中加入或修改内联函数时,使用了该内联函数的头文件的所有源文件都必须重新编译

二、类的成员函数
注意:
1)类的成员函数可以在类内定义,也可以在类外定义,但,编译器隐式地将类内定义的成员函数当作内联函数;
2)每个成员函数都有一个额外的、隐含的形参this(指针),在调用成员函数时,形参this初始化为调用函数的对象的指针;
3)const成员函数:在调用成员函数时,隐含的this指针被初始化为指向const对象的指针,因此,const成员函数不能修改调用该函数的对象
三、构造函数——特殊的成员函数


特殊性:构造函数和类同名;没有返回类型;一个类可以有多个构造函数,但不能重复
1)默认构造函数(没有形参的构造函数),在定义对象却没有提供(显式的)初始化式的时候调用的是默认构造函数
2)构造函数的初始化列表,为类的一个或多个数据成员指定初值
3)如果没有为一个类显式定义任何构造函数,编译器将自动为这个类生成默认构造函数(合成的默认构造函数),合成的默认构造函数一般适用于包
含类类型成员的类,因为类类型成员会自动调用他们的构造函数进行初始化,而内置类型或复合类型成员的类,根据变量初始化原则,在函数体内他们不会自动被初始化,因此,通常定义自己默认构造函数来初始化这些成员

四、重载函数
1)重载函数应该在同一作用域中声明,在C++中,名字查找发生在类型检查之前,因此,如果在全局定义完函数之后,又在局部重载该函数并调用
,那么该局部函数将屏蔽全局函数(因为名字查找发生在类型检查之前,在局部调用时,检查到了该重载的局部函数具有与被调用函数相同的名字,那么就会停止查找,因此全局函数将被屏蔽)
2)当函数形参与const形参为非引用时,非const形参与const形参是等价的;当函数非const形参与const形参为引用或指针时,是不等价的

例:
int search(const int);
int search(int);

等价的,第二个不是第一个函数的重载,而是重复声明
int search(const int&);
int search(int&);

不等价,第二个函数是第一个函数的重载;
3)函数确定(函数匹配)是将函数调用与重载函数集合中的一个函数相关联的过程,编译器匹配的结果有三种可能:
(1)编译器找到与实参最佳匹配的函数,并生成调用该函数的代码;
(2)找不到形参与函数调用的实参匹配的函数,编译器将给出编译错误信息;
(3)二义性,存在多个与实参匹配的函数,但没有一个是明显的最佳选择,编译器将给出编译错误信息。
4)重载确定的三个步骤:
(1)确认候选函数集合,即候选函数的名字与被调用函数的名字相同;
(2)选择可行函数,条件:函数的形参个数与该调用函数的实参个数相同;每一个实参的类型必须与对应形参的类型匹配,或可被隐式转换为对应
的形参类型
(3)如果可行函数不止一个(匹配的函数可能多个),寻找最佳匹配,即类型完全吻合的,不需要类型转换的函数
4)含有多个形参的重载确定:如果函数调用使用了两个或两个以上的显式实参,如果有且只有一个函数满足以下两个条件,则匹配成果,否则调用
错误,编译器将提示调用具有二义性:其中每个是实参的匹配都不劣于其他可行函数需要的匹配;至少有一个实参的匹配优于其他可行函数提供的
匹配
5)实参类型转换的优先级(降序)
(1)精确匹配:实参与形参类型相同
(2)通过类型提升实现的匹配
(3)通过标准转换实现的匹配
(4)通过类类型转换实现的匹配

6)形参为枚举类型,实参只能用同类型的枚举类型进行参数的传递(不能用整型);而形参为整型,实参可以用枚举类型通过类型提升进行参数传递
7)指向函数的指针
函数指针是指指向函数而非指向对象的指针;
(1)用typedef简化函数指针的定义
例:
typedef bool (*cmpFcn)(const string &,const string &);

                          //定义表示cmpFcn是一种指向函数的指针类型的名字
(2)在引用函数名但又没有调用该函数时,函数名将自动解释为指向函数的指针;
例:
bool lengthCompare(const string &,const string &);
除了用作函数调用的左操作数以外,对lengthCompare的任何使用都被解释为指向函数的指针:
bool (*)(const string &,const string &);
(3)直接引用函数名等效于在函数名上引用取地址操作符
例:
cmpFcn pf1=lengthCompare;
cmpFcn pf2=&lengthCompare; //等效于pf1
(4)函数指针只能通过同类型的函数(被转换为指向该类型指针)或函数指针或0值常量表达式进行初始化或赋值;
(5)通过指向函数的指针调用它所指向的函数,可以不使用解引用操作符;

例:
cmpFcn pf=lengthCompare;
lengthCompare("hi","bye");
pf("hi","bye");
(*pf)("hi","bye"); //等效于pf("hi","bye");

(6)函数的形参可以是指向函数的指针;
(7)返回指向函数的指针

例:
int (*f(int))(int*,int); 

       //该函数是返回值为int (*)(int*,int)的带有一个int型形参的函数f(int)
这样的形式我们可以用typedef使该定义更加简明易懂
typedef int (*PF)(int*,int);
PF f(int);

(8)允许将形参定义为函数类型,但是函数的返回类型不能为函数类型(可以为指向函数的指针)
(9)指向重载函数的指针,指针的类型必须与已有的重载函数精确匹配,否则将导致编译错误

原创粉丝点击