
心之所向 素履以往 生如逆旅 一苇以航
——七堇年 《尘曲》
柔性数组
- char data[0]或char data[] 称为柔性数组,只能放在结构体末尾。
- 作用:
- 方便管理内存缓冲区
- 减少内存碎片化
C++虚函数实现机制
虚函数的作用
简单的讲即实现多态。基类定义了虚函数,子类可以重写该函数,当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态地调用属于子类的该函数,且这样的函数调用是无法在编译器期间确认的,而是在运行时期确认,也叫作迟绑定。
C++对象模型

这个模型从结合上面2中模型的特点,并对内存存取和空间进行了优化。在此模型中,non static 数据成员被放置到对象内部,static数据成员, static and nonstatic 函数成员均被放到对象之外。对于虚函 的支持则分两步完成:
- 每个class产生一堆指向虚函数的指针,放在表格之中。这个表格称之为虚函数表(virtual table,vtbl)。
- 每一个对象被添加了一个指针,指向相关的虚函数表vtbl。通常这个指针被称为vptr。vptr的设定(setting)和重置(resetting)都由每一个class的构造函数,析构函数和拷贝赋值运算符自动完成。
另外,虚函数表地址的前面设置了一个指向type_info的指针,RTTI(Run Time Type Identification)运行时类型识别是有编译器在编译器生成的特殊类型信息,包括对象继承关系,对象本身的描述,RTTI是为多态而生成的信息,所以只有具有虚函数的对象在会生成。
Const关键字的使用方法
static关键字的使用方法
extern关键字的使用方法
运算符重载的规则
- 不可以引入新的运算符。除了. .* :: ?: 四个运算符,其他的运算符都可以被重载。
- 运算符的操作数目不可以改变。
- 运算符的优先级不可以改变。
- 运算符函数的参数列中,必须至少有一个参数为class型别。无法为诸如指针之类的non-class型别重新定义其原有的运算符,当然也无法为它引入新运算符。
位域
一种特殊的数据成员,来保存特定的位数。当程序需要将二进制数据传递给另一个程序或硬件设备的时候,通常使用位域。(位域在内存中的布局是机器相关的)
位域必须是整型数据类型,可以是signed或unsigned。通过在成员名后面接一个冒号以及指定位数的常量表达式,指出成员是一个位域:
|
|
通常最好将位域设为unsigned类型。存储在signed类型中的位域的行为由实现定义。
位域的访问方式与类的其他成员相同。例如作为类的private成员的位域只能从成员函数的定义和类的友元中访问:
|
|
通常使用内置按位操作符操纵超过一位的位域:
|
|
地址操作符(&)不能应用于位域,所以不可能有引用类位域的指针,位域也不能是类的静态成员。
volatile限定符
直接处理硬件的程序常具有这样的数据成员,它们的值由程序本身直接控制以外的过程所控制。应该将这种对象的值声明为volatile。关键字volatile是给编译器的指示,指出对这样的对象不应该执行优化。
链接指示:extern “C”
- 声明非C++函数
链接指示有两种形式:单个的或复合的。链接指示不能出现在类定义或函数定义的内部,它必须出现在函数的一次声明上。
|
|
链接指示与头文件
可以将多重声明形式应用与整个头文件。
123extern "C"{#include<srting.h>}当将#include指示放在复合链接指示的花括号中的时候,假定头文件中的所有普通函数声明都是用链接指示的语言编写的函数。
导出C++函数到其他语言
通过对函数定义使用链接指示,使得其他语言编写的程序可以使用C++函数:
12extern "C" double calc(double dparm){/* ... */}当编译器为该函数产生代码的时候,它将产生适合于指定语言的代码。
链接指示支持的语言
要求编译器支持对C语言的链接指示。编译器可以为其他语言提供链接说明。(支持什么语言随编译器而变。你必须查阅用户指南,获得关于编译器可以提供的任意非C链接说明的进一步信息)
重载函数与链接指示
链接指示与函数重载之间的相互作用依赖于目标语言。如果语言支持重载函数,则为该语言实现链接指示的编译器很可能也支持C++的这些函数的重载。
C++保证支持的唯一语言是C。C语言不支持函数重载,所以,在一组重载函数中只能为一个C函数指定链接指示。用带给定名字的C链接声明多于一个函数是错误的。
在C++程序中,重载C函数很常见,但是,重载集合中的其他函数必须都是C++函数。
extern “C” 函数的指针
编写函数所用的语言是函数类型的一部分。为了声明用其他程序设计语言编写的函数的指针,必须使用链接指示:
1extern "C" void (*pf) (int);使用pf调用函数的时候,假定该调用是一个C函数调用而编译该函数。
C函数的指针与C++函数的指针具有不同的类型,不能将C函数的指针初始化或赋值为C++函数指针(反之亦然)
应用与整个声明的链接指示
使用链接指示的时候,它应用于函数和任何函数指针,作为返回类型或形参类型使用:
1extern "C" void f1(void(*) (int));因为链接指示应用于一个声明中的所以函数,所以必须使用类型别名,以便将C函数的指针传递给C++函数:
12extern "C" typedef void FC(int);void f2(FC *);
全局变量重复定义
- 在a.h中定义了一个全局变量: int g_nVarible;
- 当在另外两个文件b.cpp和c.cpp中引用头文件a.h,使用全局变量g_nVarible时会出现错误error LNK 1169: 找到一个或多个多重定义的符号。错误原因: 因为全局变量是在a.h中的定义包含一次这个头文件,相当于又进行了一次全局变量的定义;
- 正确的书写方式:使用extern关键字,在a.h中声明全局变量g_nVarible,可以在b.cpp中定义全局变量g_nVarible,在c.cpp中不需要进行定义,只需包含头文件a.h。extern关键字告诉编译器这个变量在别处已经定义,无需进行重新的定义;
fwrite函数写入0x0A时出现错误
- 以文本方式打开文件fopen(filepath, “a”),使用fwrite函数进行16进制数据写入的时候,遇到当写入值是0x0A时,其前面总会被加上0x0D;
- 问题原因:在fwrite以文本方式写文件时,碰到0x0A时会自动在前面加上0x0D,以构成回车换行符,Linux、Windows平台的换行符默认是:0x0D 0x0A;
- 解决方法: 以二进制方式打开文件,进行写文件操作,fopen(filepath, “a + b”);
释放内存出现HEAP CORRUPTION DETECTED 错误
- 使用分配的空间越界,导致释放内存的时候出错;
