class Weapon //兵器类
{
private:
string _name; //兵器名
int _power; //威力值
public:
void show()
{
cout<< "名字:" << _name << ",威力值:" << _power <<endl;
};
void setName(string name = "赤手空拳", int power = 1);
};
void Weapon::setName(string name, int power)
{
_name = name;
_power = power;
};
int main()
{
Weapon weapon;
weapon.setName();
weapon.show();
cin.get();
return 0;
}
放在里面的默认是内联函数,声明和定义分开是个好习惯。
Show是内联函数,内联函数节省时间,但是增加空间的开销。
内联函数 在类声明的内部声明或定义的成员函数叫做内联(INLINE)函数.
有两种实现方式:
1.在类声明的内部声明,而在类声明外部定义叫做显式内联函数,如:
class display
{
int t;
public:
void output(void)
}
display object;
inline void display::output(void)
{
cout << "i is " << i <<"\n";
}
2.在类声明的内部定义,叫做隐式内联函数,如:
class display
{
int t;
public:
inline void output(void)
{cout<<"i is "<< i << "\n";}
}
引入内联函数的目的是为了解决程序中函数调用的效率问题。
函数是一种更高级的抽象。它的引入使得编程者只关心函数的功能和使用方法,而不必关心函数功能的具体实现;函数的引入可以减少程序的目标代码,实现程序代码和数据的共享。但是,函数调用也会带来降低效率的问题,因为调用函数实际上将程序执行顺序转移到函数所存放在内存中某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去前要保护现场并记忆执行的地址,转回后先要恢复现场,并按原来保存地址继续执行。因此,函数调用要有一定的时间和空间方面的开销,于是将影响其效率。特别是对于一些函数体代码不是很大,但又频繁地被调用的函数来讲,解决其效率问题更为重要。引入内联函数实际上就是为了解决这一问题。
在程序编译时,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体来进行替换。显然,这种做法不会产生转去转回的问题,但是由于在编译时将函数体中的代码被替代到程序中,因此会增加目标程序代码量,进而增加空间开销,而在时间代销上不象函数调用时那么大,可见它是以目标代码的增加为代价来换取时间的节省。
在程序中,调用其函数时,该函数在编译时被替代,而不是像一般函数那样是在运行时被调用。
使用内联函数应注意的事项
内联函数具有一般函数的特性,它与一般函数所不同之处只在于函数调用的处理。一般函数进行调用时,要将程序执行权转到被调用函数中,然后再返回到调用它的函数中;而内联函数在调用时,是将调用表达式用内联函数体来替换。在使用内联函数时,应注意如下几点:
1.在内联函数内不允许用循环语句和开关语句。
如果内联函数有这些语句,则编译将该函数视同普通函数那样产生函数调用代码,递归函数(自己调用自己的函数)是不能被用来做内联函数的。内联函数只适合于只有1~5行的小函数。对一个含有许多语句的大函数,函数调用和返回的开销相对来说微不足道,所以也没有必要用内联函数实现。
2.内联函数的定义必须出现在内联函数第一次被调用之前。
3.本栏目讲到的类结构中所有在类说明内部定义的函数是内联函数。
类的成员函数(简称类函数)是函数的一种,它的用法和作用和前面介绍过的函数基本上是一样的,它也有返回值和函数类型,它与一般函数的区别只是:它是属于一个类的成员,出现在类体中。它可以被指定为private(私有的)、public (公用的)或protected(受保护的)。
在使用类函数时,要注意调用它的权限(它能否被调用)以及它的作用域(函数能使用什么范围中的数据和函数)。例如私有的成员函数只能被本类中的其它成员函数所调用,而不能被类外调用。成员函数可以访问本类中任何成员(包括私有的和公用的),可以引用在本作用域中有效的数据。
一般的做法是将需要被外界调用的成员函数指定为public,它们是类的对外接口。但应注意,并非要求把所有成员函数都指定为public。有的函数并不是准备为外界调用的,而是为本类中的成员函数所调用的,就应该将它们指定为private。这种函数的作用是支持其它函数的操作,是类中其它成员的工具函数(utility function),类外用户不能调用这些私有的工具函数。
类的成员函数是类体中十分重要的部分。如果一个类中不包含成员函数,就等同于C语言中的结构体了,体现不出类在面向对象程序设计中的作用。
在类外定义成员函数
在前面已经看到成员函数是在类体中定义的。也可以在类体中只写成员函数的声明,而在类的外面进行函数定义。如:
1. class Student
2. {
3. public :
4. void display( ); //公用成员函数原型声明
5. private :
6. int num;
7. string name;
8. char sex;
9. //以上3行是私有数据成员
10. };
11. void Student::display( )//在类外定义display类函数
12. {
13. cout<<"num:"<<num<<endl;
14. cout<<"name:"<<name<<endl;
15. cout<<"sex:"<<sex<<endl;
16. }
17. Student stud1,stud2; //定义两个类对象
注意:在类体中直接定义函数时,不需要在函数名前面加上类名,因为函数属于哪一个类是不言而喻的。
但成员函数在类外定义时,必须在函数名前面加上类名,予以限定(qualifed)," :: "是
作用域限定符(field qualifier)
或称
作用域运算符
,用它声明函数是属于哪个类的。
如果在作用域运算符“::”的前面没有类名,或者函数名前面既无类名又无作用域运算符“::”,如
::display( ) 或 display( )
则表示display函数不属于任何类,这个函数不是成员函数,而是全局函数,即非成员函数的一般普通函数。
类函数必须先在类体中作原型声明,然后在类外定义,也就是说类体的位置应在函数定义之前,否则编译时会出错。
虽然函数在类的外部定义,但在调用成员函数时会根据在类中声明的函数原型找到函数的定义(函数代码),从而执行该函数。
在类的内部对成员函数作声明,而在类体外定义成员函数,这是程序设计的一种良好习惯。如果一个函数,其函数体只有2-3行,一般可在声明类时在类体中定义。多于3行的函数,一般在类体内声明,在类外定义。
inline 成员函数
关于内置(inline )函数,在前边已经作过介绍,请猛击: C++内置函数
。类的成员函数也可以指定为内置函数。
在类体中定义的成员函数的规模一般都很小,而系统调用函数的过程所花费的时间开销相对是比较大的。调用一个函数的时间开销远远大于小规模函数体中全部语句的执行时间。为了减少时间开销,如果在类体中定义的成员函数中不包括循环等控制结构,C++系统会自动将它们作为内置(inline)函数来处理。
也就是说,在程序调用这些成员函数时,并不是真正地执行函数的调用过程(如保留返回地址等处理),而是把函数代码嵌入程序的调用点。这样可以大大减少调用成员函数的时间开销。C++要求对一般的内置函数要用关键字inline声明,但对类内定义的成员函数,可以省略inline,因为这些成员函数已被隐含地指定为内置函数。如:
1. class Student
2. {
3. public :
4. void display( )
5. {
6. cout<<"num:"<<num<<endl;cout<<"name:"
7. <<name<<endl;cout<<"sex:"<<sex<<endl;
8. }
9. private :
10. int num;
11. string name;
12. char sex;
13. };
其中第3行
void display( )
也可以写成
inline void display( )
将display函数显式地声明为内置函数。
以上两种写法是等效的。对在类体内定义的函数,一般都省写inline。
应该注意的是,如果成员函数不在类体内定义,而在类体外定义,系统并不把它默认为内置(inline )函数,调用这些成员函数的过程和调用一般函数的过程是相同的。如果想将这些成员函数指定为内置函数,应当用inline作显式声明。
如:
1. class Student
2. {
3. public : inline void display( );//声明此成员函数为内置函数
4. private :
5. int num;
6. string name;
7. char sex;
8. };
9.
10. inline void Student::display( ) // 在类外定义display函数为内置函数
11. {
12. cout<<"num:"<<num<<endl;cout<<"name:"<<name<<endl;cout<<"sex:"<<sex<<endl;
13. }
在前面曾提到过,在函数的声明或函数的定义两者之一作inline声明即可。值得注意的是,如果在类体外定义inline函数,则必须将类定义和成员函数的定义都放在同一个头文件中(或者写在同一个源文件中),否则编译时无法进行置换(将函数代码的拷贝嵌入到函数调用点)。但是这样做,不利于类的接口与类的实现分离,不利于信息隐蔽。虽然程序的执行效率提高了,但从软件工程质量的角度来看,这样做并不是好的办法。只有在类外定义的成员函数规模很小而调用频率较高时,才将此成员函数指定为内置函数