一步一步学习C++(类)之成员函数的特性
一.内联函数和外联函数
使用内联函数应注意的事项
内联函数具有一般函数的特性,它与一般函数所不同之处公在于函数调用的处理。一般函数进行调用时,要将程序执行权转到被调用函数中,然后再返回到调用它的函数中;而内联函数在调用时,是将调用表达式用内联函数体来替换。在使用内联函数时,应注意如下几点:
1.一个函数可以自已调用自已,称为递归调用(后面讲到),含有递归调用的函数不能设置为inline;
2.使用了复杂流程控制语句:循环语句和switch语句,无法设置为inline;
3.由于inline增加体积的特性,所以建议inline函数内的代码应很短小。最好不超过5行。
4.inline仅做为一种“请求”,特定的情况下,编译器将不理会inline关键字,而强制让函数成为普通函数。出现这种情况,编译器会给出警告消息。
5.在你调用一个内联函数之前,这个函数一定要在之前有声明或已定义为inline,如果在前面声明为普通函数,而在调用代码后面才定义为一个inline函数,程序可以通过编译,但该函数没有实现inline。
总结为几句话
1.在内联函数内不允许用循环语句和开关语句。
2.内联函数的定义必须出现在内联函数第一次被调用之前。
只要声明为内联,编译器就不把它编译成一次函数调用,而只是类似于把函数的代码拷贝到被调用的地方,而且这完全是编译器私下里完成的,原来的访问权限等问题丝毫不受影响。这不是两全齐美了吗:在保证代码的面向对象性和结构化不受损失的条件下,程序的效率也没有损失。
Class MyClass { public: inline int GetState(); private: int m_iState; } int inline MyClass::GetState() { return m_iState; }
内联函数还有另外一种写法,就是直接写在类中,此时,不必使用“inline”关键字。
class MyClass { public: int GetState() { return m_iState; } private: int m_iState; };内联函数只是一种编译机制,用上面两种形式声明的函数仅仅是建议编译器进行内联,而编译器是否内联不一定。正如前面所说,函数调用的开销只是对小的函数不可忽略,对于重量级的函数还是可以忽略的,而且在绝大多数的场合,函数调用才是人间正道,才是解决问题的最佳。所以大多数编译器并不把带有循环、递归等或者代码比较多的函数进行内联编译,有的甚至不允许声明成内联的。
二.静态成员
static主要有三个作用:
(1)局部静态变量
(2)外部静态变量/函数
(3)静态数据成员/成员函数class MyClass { public: int GetState() { return m_iState; } private: int m_iState; static int a;//定义 } ; <span style="color:#ff0000;"> </span>int MyClass::a = 0;//初始化
2.2 静态数据成员被 类 的所有对象所共享,包括该类派生类的对象。即派生类对象与基类对象共享基类的静态数据成员
// StaticForClass.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" class MyClass { public: int GetState() { return m_iState; } static int a; //定义 private: int m_iState; }; int MyClass::a = 0;//初始化 class DerivedClass:public MyClass { }; int _tmain(int argc, _TCHAR* argv[]) { MyClass A; DerivedClass B; printf("%d\n",A.a); A.a++; printf("%d\n",B.a); getchar(); return 0; }<span style="color:#ff0000;"> </span>
三、静态成员函数
3.1 静态成员函数的地址可用普通函数指针储存,而普通成员函数地址需要用 类成员函数指针来储存// StaticForClass.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" class MyClass { public: static int GetState(); void print(); static int a; //定义 private: int m_iState; }; int MyClass::a = 0;//初始化 int MyClass::GetState()//静态函数的调用 { return a; //return m_iState;/* error C2597: 对非静态成员“MyClass::m_iState”的非法引用*/ } void MyClass::print() { printf("%d",a); } class DerivedClass:public MyClass { }; int _tmain(int argc, _TCHAR* argv[]) { #if 0 MyClass A; DerivedClass B; printf("%d\n",A.a); A.a++; printf("%d\n",B.a); #endif int (*pf1)() = &MyClass::GetState;//普通的函数指针 //int (MyClass::*pf2)() = &MyClass::GetState; /*error C2440: “初始化”: 无法从“int (__cdecl *)(void)”转换为“int (__thiscall MyClass::* )(void)”*/ void (MyClass::*pf3)() = &MyClass::print;//普通的函数指针 getchar(); return 0; }
class MyClass { public: static int GetState();//静态函数 static int a; //定义 private: int m_iState; }; int MyClass::a = 0;//初始化 int MyClass::GetState()//静态函数的调用 { return a; //return m_iState;/* error C2597: 对非静态成员“MyClass::m_iState”的非法引用*/ }
1、出现在类体外的函数定义不能指定关键字static;
2、静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
4、静态成员函数不能访问非静态成员函数和非静态数据成员;
5、由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长;
6、调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数,
7、当同一类的所有对象使用一个量时,对于这个共用的量,可以用静态数据成员变量,这个变量对于同一类的所有的对象都取相同的值。静态成员变量只能被静态成员函数调用。静态成员函数也是由同一类中的所有对象共用。只能调用静态成员变量和静态成员函数。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。