成员函数
成员函数:
成员函数生命必须在类的内部,但是定义可以在类的内部也可以在类的外部。
定义在类的内部的成员函数都被默认为inline属性。同时也可以在类中声明成员函数时为inline,在外部定义时用inline修饰,也同样达到内联的目的。(一般inline修饰的成员函数定义应该和类一样位于头文件中)。
同时成员函数也可以重载,重载的机制规则与普通函数一样。
详细说一下定义在类外部的成员函数:
定义在类外部的函数为了让编译器知道属于哪个类,要在函数名前面加上类作用域来指明是属于哪个类的。但是这个作用域仅仅限制于参数和函数体。如果返回类型是类中类型成员,则要对返回类型加上类作用域。
&与外界交互接口的问题:
在任意一个成员函数中都有一个隐式的参数——this,有了这个参数,使得在调用成员函数时不再传入类类型对象的地址,在成员函数中使用类的数据成员时不再使用this->member复杂的形式,而是仅仅使用数据成员即可。This本质是一个常量类型指针(class_name * const)在成员函数中不能出现this的参数和变量。(另一层原因是因为this是一个关键字),如果类类型对象为常量则this类型为(const class_name * const)
在设计接口时,成员函数的参数和返回类型直接与类类型对象息息相关。类类型对象是常量还是非常量直接影响着类的设计。如果定义的类类型对象为常量类型,那么只能调用常量成员函数。如果定义类类型对象为变量类型,那么可以调用非常量成员函数也可以调用常量成员函数。
为了使得定义的类能够面向常量类型也能变量非常量类型,则要对类进行有规划的设计。(假如定义的常量类型的对象和非常量类型的对象都调用一个print成员函数(该函数返回*this),但是这个成员函数对类中数据成员不做修改,原则上要声明为常量成员函数,但是当非常量对象调用print函数时,返回是一个const class_name * const类型的引用,当在连续调用另一个接口时,如果这个成员函数为常量成员函数可以工作,但是如果是非常量成员函数,那么就会发生错误,所以print必须声明为非常量成员函数。但是当常量对象调用print函数时本应为常量成员函数(不误常量成员函数发生错误)。对于操作类的成员函数,非常量成员函数不能被常量对象调用。)所以print可以函数重载,声明两个print函数一个为常量成员函数,一个为非常量成员函数。声明这两个print成员函数仅仅在接口处理上不同,在函数体内执行的操作相同。我们可以对公共的部分进行私有(private)功能函数化,这样既可以避免了程序的冗余,方便了修改,同时也不会增加多余的函数调用的开销(因为私有功能函数声明在类中private权限,隐式的定义为inline,所以不会增加开销)。
对于返回类型,特别强调的是如果返回一个类类型对象(左值),要用return*this,同时用一个对应this类型的引用承接。
&编译器对类中名字的解析方式:
编译时处理完类中的全部声明后才能处理成员函数的定义,但仅适用于成员函数体中使用的数据成员,如果在声明中使用类型成员,返回类型或参数列表中使用类型成员,就要必须保证在使用之前可见。
{比如,在一条声明成员函数的语句中返回类型为money,编译器就要先对类中,这条语句前的空间内找是否有对money类型的声明,如果没有,则要找类之外。}注意,并不是在类中找完声明语句之前还要找之后的,对之后的直接忽略。所以类型名的定义语句定义在类的开始部分这样确保使用该类型的成员都在类中。同时也不允许在声明语句之前定义一个数据,之后还要定义。
&成员定义中普通快作用域名字查找:
先在成员函数中查找名字声明。
在类中查找声明(所有声明都查)。
成员函数定义之前的作用域内查找。