C++类的底层实现机制

我们首先从一个问题来阐明类的底层机理:

假如有一个类A。里面有一个成员函数get(),比如:

A的头文件

        定义A a; 那么a.get()表示什么呢?首先给出答案是get(&a),由于在类的底层机制中,成员函数的第一个參数都是一个指向该类数据结构的指针(静态成员函数除外),所以成员函数get()的存在形式为void get(A* this);这也能说明为什么我们在成员函数的定义中总是能够用this来指代调用对象。

        我们知道,要使用一个C++类。必要的条件是在编译期能得到这个类的头文件,并在链接期能够找到相应的符号的链接地址(比方成员函数、静态数据成员等)。假设这个C++类与你的使用者在同一个project。那这个条件非常好满足:

        首先。C++类的头文件非常好获得。直接在使用者那里将类的头文件include就可以。

        其次,C++类往往被编译器作为一个编译单元,生成一个obj文件。

        在最后进行链接的过程中,链接器会把project中全部的obj链接以生成终于的二进制目标文件。所以链接器在遇到一处对类成员函数(或其他形式的符号引用)时,会在这个类生成的obj文件里找到符号的链接地址。

        那么,在代码中使用一个C++类,编译期和链接期须要的究竟是些什么东西呢?换句话说。满足了什么样的条件。编译器和链接器就不会抱怨了呢?依据C++语言的定义。一个C++类实际上是声明或定义了例如以下几类内容:

        1.声明了一个数据结构。类中的非静态数据成员; 和代码中看不到但假设有虚函数就会生成的虚表入口地址指针等。

        2.声明并定义了一堆函数,它们第一个參数都是一个指向这个数据结构的指针。这些实际上就是类中那些非静态成员函数(包含虚函数),它们尽管在类声明中是写在类的一对大括号内部。但实际上没有什么东西被加到前面第1条中所说的内部数据结构中。实际上。这种声明仅仅是为这些函数添加了两个属性:函数名标识符的作用域被限制在类中;函数第一个参数是this,被省略不写了。

        3.声明并定义了还有一堆静态函数。它们看上去就是一些普通函数,与这个类差点儿没有关系。这些实际上就是类中那些静态函数。它们也是一样,不会在第1条中所说的内部数据结构中添加什么东西,仅仅是函数名标识符的作用域被限制在类中。

        4.声明并定义了一堆全局变量。这些实际上就是类中那些静态数据成员。

        5.声明并定义了一个全局变量。此全局变量是一个函数指针数组,用来保存此类中全部的虚函数的入口地址。当然,这个全局变量生成的前提是这个类有虚函数。

看以下的一个样例:

MyClass

对于上面列出的这个类MyClass,C++编译器多数会以例如以下的方式进行编译:

编译结构

如今我们再来看一下为什么编译器须要头文件和符号地址就能够编译链接一个使用MyClass的程序了。

        首先,因为编译器须要在编译期就知道类的内存布局,以保证能够生成正确的开辟内存的代码。及sizeof(MyClass)的值。有了头文件,编译器就知道,一个MyClass占用12字节的内存空间(见上图,两个整数和一个指针)。

        其次,在调用MyClass的成员函数、静态函数时,链接器须要知道这些函数的入口地址,假设无法提供入口地址,链接器就会报错。

        最后。在引用MyClass的静态数据成员时,实际上与引用一个外部全局对象一样,链接器须要知道这些变量的地址。假设无法提供这些变量的地址,链接器也会报错。

能够看出:

1. 编译期:必需要提供的是类的头文件,以使编译器能够得知类实例的尺寸和内存布局。

2. 链接期:必需要提供的是程序中引用过的,类的成员函数、静态函数、静态数据成员的地址。以使链接器能够正确的生成终于程序。

    到这里,我们能够猜到。实际上。导出一个类。编译器实际上仅仅须要将这个类中的:成员函数、静态函数、静态数据成员当成普通的函数、全局变量导出就可以。也就是说。我们实际上没有“导出一个类”。而是把这个类中须要被引用的“有定义的实体”的入口地址像普通函数和变量那样正常导出就可以。因为里面的纯虚函数VBar没有定义,所以不会被导出。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342