C++工具机关及多态实现摸索之内存机关
副标题#e#
为了便于阐明和调查工具的内存机关,我把代码生成时的布局成员对齐选项配置为1字节,默认为8字节。假如你在本身的工程下编译文中的代码,请做同样的配置。因为我写了一些函数打印工具中的机关信息,假如工具选项不是1字节,运行这些代码会呈现指针异常错误。
普通类工具的内存机关
首先我们从普通类工具的内存机关开始。c000为一个空类,界说如下:
struct c000
{};
运行如下代码打印它的巨细及工具中的内容。
print_size_detail(c000)
功效为:
the size of c000 is 1
the detail of c000 is cc
可以看到它的巨细为1字节,这是一个占位符。我们可以看到它的值是0xcc。在debug模式下,这暗示是由编译器插入的调试代码所初始化的内存。在release模式下大概是个随机值,我测试时值为0x00。
界说两个类,c010和c011如下:
struct c010
{
c010() : c_(0x01) {}
void foo() { c_ = 0x02; }
char c_;
};
struct c011
{
c011() : c1_(0x02), c2_(0x03) {}
char c1_;
char c2_;
};
运行如下代码打印它们的巨细及工具中的内容。
print_size_detail(c010)
print_size_detail(c012)
功效为:
the size of c010 is 1
the detail of c010 is 01
the size of c011 is 2
the detail of c011 is 02 03
我们从工具的内存输出中可以看到,它们的值就是我们在结构函数中赋的值,c010为0x01,c011为0x0203。巨细别离为1、2。
#p#副标题#e#
界说c012类。
struct c012
{
static int sfoo() { return 1; }
int foo() { return 1; }
char c_;
static int i_;
};
int c012::i_ = 1;
在这个类中我们插手了一个静态数据成员,一个普通成员函数和一个静态成员函数。
运行如下代码打印它的巨细及工具中的内容。
print_size_detail(c012)
功效为:
the size of c012 is 1
the detail of c012 is cc
可以看到它的巨细照旧1字节,值为0xcc是因为我们没有初始化它,原因前面说过了。
从上面的功效我们可以映证,普通成员函数,静态成员函数,及静态成员变量皆不会在类的工具中有所暗示,成员函数和工具的关联由编译器在编译时处理惩罚,正如我们会在后头看到的那样,编译器会在编译时决策出正确的普通成员函数地点,并将工具的地点以this指针的方法,做为第一个参数通报给普通成员函数,以此来举办关联。静态成员函数雷同于全局函数,反面详细的工具关联。静态成员变量也一样。静态成员函数和静态成员变量和普通的全局函数及全局变量差异之处在于它们多了一层名字限定。
普通担任类工具的内存机关
下面看看普通担任类工具的内存机关。
界说一个空类c014从c011担任,再界说c015也是一个空类从c010和c011担任。
struct c010
{
c010() : c_(0x01) {}
void foo() { c_ = 0x02; }
char c_;
};
struct c011
{
c011() : c1_(0x02), c2_(0x03) {}
char c1_;
char c2_;
};
struct c014 : private c011
{};
struct c015 : public c010, private c011
{};
运行如下代码打印它们的巨细及工具中的内容。
print_size_detail(c014)
print_size_detail(c015)
功效为:
the size of c014 is 2
the detail of c014 is 02 03
the size of c015 is 3
the detail of c015 is 01 02 03
c014的巨细为2字节,也就是c011的巨细,工具的内存值也是在c011的结构函数中初始化的两个值0x0203。c015的巨细为3字节,也就是c010和c011的巨细之和,工具的内存值为0x010203。
这里我们可以发明父类的成员变量悉数被子类担任,而且于担任方法(公有或私有)无关,如c015是私有担任自c011。担任方法只影响数据成员的“能见度”。子类工具中属于从父类担任的成员变量由父类的结构函数初始化。凡是会挪用默认结构函数,除非子类在它的结构函数初始化列表中显式挪用父类的非默认结构函数。假如没有指定,而父类又没有缺省结构函数,则会发生编译错误。
我们可以再加一层担任来验证一下。界说类c016,从c015担任,并有本身的4字节int成员变量。
struct c016 : c015
{
c016() : i_(1) {}
int i_;
};
运行如下代码打印它的巨细及工具中的内容。
print_size_detail(c016)
功效为:
the size of c016 is 7
the detail of c016 is 01 02 03 01 00 00 00
#p#分页标题#e#
它的巨细为7字节,也就是c015的巨细(也等于c010和c011的巨细和)加上自身的4字节int变量之和。同样工具的内存输出也验证了这一点,前三个字节为从父类担任的,后4个字节为自身的int变量,值为1。
因此关于普通担任,子类的工具机关为父类中的数据成员加上子类中的数据成员,多层担任时(如c016),顶层类在前,多重担任时则最左父类在前。