设为首页 加入收藏

TOP

C++对象在继承情况下的内存布局(一)
2019-05-24 10:15:22 】 浏览:176
Tags:对象 继承 情况 内存 布局

1,C++ 中继承是非常重要的一个特性,本节课研究在继承的情形下,C++ 的对象模 型又有什么不同;  

 

2,继承对象模型(最简单的情况下):

    1,在 C++ 编译器的内部类可以理解为结构体;

    2,子类是由父类成员叠加子类新成员得到的;

       1,代码示例:

1 class Derived : public Demo

2 {

3 int mk;

4 }; 

       2,对象排布:

 

           1,在对象模型中,先排布父类对象模型,再排布子类对象模型,见 本文3中内容;

   

3,继承对象模型初探编程实验:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 class Demo
 7 {
 8 protected:
 9     int mi;
10     int mj;
11 public:
12     virtual void print()
13     {
14         cout << "mi = " << mi << ", "
15              << "mj = " << mj << endl;
16     }
17 };
18 
19 class Derived : public Demo
20 {
21     int mk;
22 public:
23     Derived(int i, int j, int k)
24     {
25         mi = i;
26         mj = j;
27         mk = k;
28     }
29     
30     void print()
31     {
32         cout << "mi = " << mi << ", "
33              << "mj = " << mj << ", "
34              << "mk = " << mk << endl;
35     }
36 };
37 
38 struct Test
39 {
40     void* p;  // 为了证明 C++ 编译器真的会在对象中塞入一个指针成员变量,且指针放在最开始的字节处;    
41     int mi;
42     int mj;
43     int mk;
44 };
45 
46 int main()
47 {
48     cout << "sizeof(Demo) = " << sizeof(Demo) << endl; // 8 bytes         
49     cout << "sizeof(Derived) = " << sizeof(Derived) << endl;  // 12 bytes
50     
51     Derived d(1, 2, 3);
52     Test* p = reinterpret_cast<Test*>(&d);
53     
54     cout << "Before changing ..." << endl;
55     
56     d.print();  // mi = 1, mj = 2, mk = 3;
57 
58     /* 通过 p 对象改变成员变量的值,这里加了 p 指针后任然能够成功的访问; */    
59     p->mi = 10;
60     p->mj = 20;
61     p->mk = 30;
62     
63     cout << "After changing ..." << endl;
64     
65     d.print();  // mi = 10, mj = 20, mk = 30;在外界访问不到的保护成员变量的值被改变了,改变是因为 d 对象的内存分布 Test 结构体的(此时类中未有虚函数,Test 中未有 空指针),因此可以用 p 指针改变 d 对象当中成员变量的值;
66     
67     return 0;
68 }

 

   

4,多态对象模型:

    1,C++ 多态的实现原理:

       1,当类中声明虚函数时,编译器会在类中生成一个虚函数表;

       2,虚函数表是一个存储成员函数地址的数据结构;

           1,存储虚函数成员地址的数据结构;

       3,虚函数表是由编译器自动生成与维护的;

       4,virtual 成员函数会被编译器放入虚函数表中;

           1,这个表是给对象使用的;

           2,对象在创建时,在内部有一个虚函数表指针,这个指针指向虚函数表;

       5,存在虚函数时,每个对象中都有一个指向虚函数表的指针;

    2,框图展示:

  1,框架一

 

         1,编译父类时,编译器发现了 virtual 成员函数,因此编译器创建了一个虚函数表,并且将虚函数的地址放到了虚函数表里面;

         2,编译子类时,继承自 Demo,编译器发现重写了 add 函数,因此必须是虚函数,于是编译器就为子类也生成一张虚函数表,并且也会在虚函数表中放入重写过后的 add 虚函数的地址;

  2,框架二

 

          1,当创建父类对象的时候,会为 Demo 对象自动的塞入一个指针 VPTR,也 就是如果类中有虚函数的话,在最终生成类对象的时候,会被编译器强         制赛一个指针成员变量,这个指针成员变量对于程序员是不可见的,但是它确确实实的会存在对象当中,这个指针成员变量指向了虚函数表;

         2,当创建子类对象的时候,会为 Derived 对

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C++中的多重继承(一) 下一篇深入V8引擎-Time模块介绍

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目