C++经典对象模型题

1、我们先来看第一道:

[cpp]  view plain  copy
  1. #include<iostream>  
  2. using namespace std;  
  3. class A  
  4. {  
  5. public:  
  6.     A()  
  7.     {  
  8.         m_a = 1;  
  9.         m_b = 2;  
  10.     }  
  11.     void fun()  
  12.     {  
  13.         cout<<m_a<<" "<<m_b<<endl;  
  14.     }  
  15. private:  
  16.     int m_a;  
  17.     int m_b;  
  18. };  
  19. class B  
  20. {  
  21. public:  
  22.     B()  
  23.     {  
  24.         m_c = 3;  
  25.     }  
  26.     void fun()  
  27.     {  
  28.         cout<<m_c<<endl;  
  29.     }  
  30. private:  
  31.     int m_c;  
  32. };  
  33. int main()  
  34. {  
  35.     A a;  
  36.     B* pb =(B*)(&a);  
  37.     pb->fun();  
  38.     return 0;  
  39. }  
1)程序运行结果:1

2)我们来分析下:

    a:先来看A和B的对象模型:


    b:Bl类型的对象pb取a的地址并将其转换成B类型的,因此就有指针pb指向A对象模型的首地址,接着pb调用fun()函数,此时的fun()函数是类B的函数,要输出_c的值就取刚才指向的A中的前四个字节,即_a的值,于是程序运行结果就是1。

2、第二道:

描述:上面例子,让类B公有继承自类A

[cpp]  view plain  copy
  1. #include<iostream>  
  2. using namespace std;  
  3. class A  
  4. {  
  5. public:  
  6.     A()  
  7.     {  
  8.         m_a = 1;  
  9.         m_b = 2;  
  10.     }  
  11.     void fun()  
  12.     {  
  13.         cout<<m_a<<" "<<m_b<<endl;  
  14.     }  
  15. private:  
  16.     int m_a;  
  17.     int m_b;  
  18. };  
  19. class B:public A  
  20. {  
  21. public:  
  22.     B()  
  23.     {  
  24.         m_c = 3;  
  25.     }  
  26.     void fun()  
  27.     {  
  28.         cout<<m_c<<endl;  
  29.     }  
  30. private:  
  31.     int m_c;  
  32. };  
  33. int main()  
  34. {  
  35.     A a;  
  36.     B* pb =(B*)(&a);  
  37.     pb->fun();   
  38.     return 0;  
  39. <span style="color:#009900;">}</span>  
1)程序运行结果:随机数

2)来分析:

   a:先来看对象模型


   b:跟上面类似,不过在pb调用fun函数的时候,它会将A的对象模型认为是自己的,在打印_c的时候,因为A中没有第三个值,所以程序运行结果是随机值。

3、将第二道题做些改变:让A中的函数成为虚函数

[cpp]  view plain  copy
  1. #include<iostream>  
  2. using namespace std;  
  3. class A  
  4. {  
  5. public:  
  6.     A()  
  7.     {  
  8.         m_a = 1;  
  9.         m_b = 2;  
  10.     }  
  11.     virtual void fun()  
  12.     {  
  13.         cout<<m_a<<" "<<m_b<<endl;  
  14.     }  
  15. private:  
  16.     int m_a;  
  17.     int m_b;  
  18. };  
  19. class B:public A  
  20. {  
  21. public:  
  22.     B()  
  23.     {  
  24.         m_c = 3;  
  25.     }  
  26.     void fun()  
  27.     {  
  28.         cout<<m_c<<endl;  
  29.     }  
  30. private:  
  31.     int m_c;  
  32. };  
  33. int main()  
  34. {  
  35.     A a;  
  36.     B* pb =(B*)(&a);  
  37.     pb->fun();     
  38.     return 0;  
  39. }  
1)程序运行结果:1 2

2)程序分析:

   a:对象模型分析


   b:程序分析:A中的对象模型多了一个虚表指针,在pb调用fun函数的时候,此时因为是虚函数,所以它会去调用实际的对象所指的函数类型,此时它调用的是A类的fun函数,通过虚表指针找到实际的虚函数地址,正是A中的fun函数,因此程序运行结果就是_a,_b的值:1 2

4、这道题是第三题的变形:将B中的函数设为虚函数,而A中的函数设为普通函数  

[cpp]  view plain  copy
  1. #include<iostream>  
  2. using namespace std;  
  3. class A  
  4. {  
  5. public:  
  6.     A()  
  7.     {  
  8.         m_a = 1;  
  9.         m_b = 2;  
  10.     }  
  11.     void fun()  
  12.     {  
  13.         cout<<m_a<<" "<<m_b<<endl;  
  14.     }  
  15. private:  
  16.     int m_a;  
  17.     int m_b;  
  18. };  
  19. class B:public A  
  20. {  
  21. public:  
  22.     B()  
  23.     {  
  24.         m_c = 3;  
  25.     }  
  26.     virtual void fun()  
  27.     {  
  28.         cout<<m_c<<endl;  
  29.     }  
  30. private:  
  31.     int m_c;  
  32. };  
  33. int main()  
  34. {  
  35.     A a;  
  36.     B* pb =(B*)(&a);   
  37.     pb->fun();   
  38.     return 0;  
  39. }  
1)程序的运行结果:程序崩溃

2)程序运行结果分析:

   a:对象模型的分析


   b:程序结果分析:此时pb多了一个虚表指针,当pb调用fun函数的时候,此时pb还是指向A的对象模型,但是,pb会向上挪动四个字节,而访问挪动后的空间,程序必然崩溃。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值