匈牙利命名法 scope_prefix_qualifier 作用域_前缀_标识符 前缀 类型 例子 g 全局变量域 g_Servers m 局部作用域 m_pDoc |
表1 prefix前缀表
前缀 | 类型 | 例子 |
ch | char | chGrade |
b | bool | bEnable |
n | int | |
p | * | pDoc |
lp | Far*(Far Pointer) | lpDoc |
h | handle | hWnd |
st | struct | stPerson |
提高代码可读性的手段:
- 清晰地表达意图。比如const关键字的使用,static 关键字等。
- 一个方法只做一件事情。同一个方法体内,保持相同的抽象层次。
- 不要重复自己。
- 命名规范。
- 编写良好注释。
>>>>>内联函数
内联函数是在“编译期”完成的,而虚拟函数支持下的多态是在运行期实现的,本质上在“编译期”编译器无法知道某处的虚拟函数调用在真正执行的时候会调用哪个具体的实现。
如果想利用虚拟函数的“动态绑定”带来的设计优势,那么必须放弃“内联函数”带来的速度优势。
在类的定义中同时实现类的成员函数时,编译器会自动尝试内联,即不需要手动添加inline关键字。
当在类的定义外实现类的成员函数时,需要手动添加inline关键字才能实现内联。
>>>>>>临时对象是c++语言中的特征是未出现在源代码中,从堆栈中产生的未命名对象。而且开发人员往往都不会意识到它们的存在。它们完全是编译器根据情况产生的。
产生临时对象一般来说有两种场合:
- 当实际调用函数时传入的参数与函数定义中声明的参数类型不匹配。
- 当函数返回一个对象时
》》》虚函数
虚函数表指针,虚函数表 - LEAKERS_ZZW的专栏 - 博客频道 - CSDN.NET
注:这篇博文可能就是参考《编码的法则》这本书写的。
无故的声明虚析构函数和永远不去声明一样是错误的。实际上,很多人这样总结:当且仅当类里包含至少一个虚函数的时候才去声明虚析构函数。
总结(基类有虚函数):
- 编译器会为每个有虚函数的类创建一个虚函数表,该虚函数表将被该类的所有对象共享。 (这个表的大小跟该类拥有的虚函数的多少成正比,这里所说的”该类拥有的“包括从基类继承来的,再加上派生类本身的,再除去在派生类中重写掉的)
- 虚表可以继承,如果子类没有重写虚函数,那么子类虚表中仍然会有该函数的地址,只不过这个地址指向的是基类的虚函数实现。如果基类有3个虚函数,那么基类的虚表中就有三项(虚函数地址),派生类也会有虚表,至少有三项,如果重写了相应的虚函数,那么虚表中的地址就会改变,指向自身的虚函数实现。如果派生类有自己的虚函数,那么虚表中就会添加该项。
- 派生类的虚表中虚函数地址的排列顺序和基类的虚表中虚函数地址排列顺序相同。
- 关于多继承下的虚函数表见
虚拟函数开销
空间:通过支持虚拟当函数的类生成的每个对象都有一个指向该类对应的虚拟函数表的虚拟函数指针,无论该类的虚拟函数有多少个,都只有一个函数指针。但因为与对象绑定,所以程序运行时因为虚拟函数指针引起的开销与生成的对象的个数成正比。
时间:通过支持虚拟函数的类生成的每个对象,当其生成时,在构造函数中会调用编译器在构造函数内部插入的初始化代码来初始化其虚函数指针,使其指向正确的虚函数表。(对于多继承的情况,派生类对象中可能有多个基类对应的虚函数表指针。)
时间:调用虚函数时,相比普通函数会多一个根据虚拟函数指针找到虚函数表的操作。
btw,虚基类???