用指针访问私有数据和函数的探讨

例一:
             int f[4]={111,222,333,444};
           cout<<f<<endl;
           cout<<&f<<endl;
           cout<<&f[0]<<endl;

          cout<<(f+1)<<endl;
          cout<<&f[1]<<endl;
           cout<<((int*)&f+1)<<endl;
           cout<<(&f+1)<<endl;
上述代码的运行结果为:
            可以看出取址符&去掉了指针的类型,对于任意变量取地址,如果直接+1,经过测试一般情况下是增加了16.
            把这些地址看做指针,指针+1,代表移动了一个位的长度,所以可以看出((int*)&f+1),是在原始地址上增加了一个int,4位的长度。
           比较下面的代码我们可以进一步看出这个区别:
          cout<<((int*)&f+1)<<endl;
          cout<<((double*)&f+1)<<endl;
          
         
           所以通过指针访问f[2],下面三种方式都正确
           cout<<f[2]<<endl;
           cout<<*(f+2)<<endl;
          cout<<*((int*)&f+2)<<endl;

          下面2种方式都是错误的
         cout<<*(&f+2)<<endl;
         cout<<*((double*)&f+1)<<endl;//虽然得到的地址(double*)&f+1和(int*)&f+2是一致的。

而通过指针方式,我们可以访问到类的私有成员,在正规情况下这些私有成员是无法被访问到的。
class CBase
{
private:
     int m_data1;
     virtual void vfunc1(){cout<<"CBase vfunc1"<<endl;}

public:
     int m_data2;
     void func1(){cout<<"CBase func1"<<endl;}
     void func2(){cout<<"CBase func2"<<endl;}


    virtual void vfunc2(){cout<<"CBase vfunc2"<<endl;}
     void set_data1(int m){m_data1=m;m_data2=889;}

};

class Cchild:public CBase
{
public:
     int m_data1;
     int m_data3;
     void func2(){cout<<"Cchild func2"<<endl;}
     void func3(){cout<<"Cchild func3"<<endl;}
     virtual void vfunc2(){cout<<"Cchild vfunc2"<<endl;}
     virtual void vfunc3(){cout<<"Cchild vfunc3"<<endl;}
};

/*class classC:public classB
{
public:
     int m_data1;
     int m_data4;
     void func2(){cout<<"class c"<<endl;}
     virtual void  vfunc1(){}
};*/

void main()
{
     cout<<sizeof(CBase)<<endl;//结果为什么是12,是因为2个int,加一个虚函数表指针
     cout<<sizeof(Cchild)<<endl;//结果是20,是因为4个int,加一个虚函数表指针

     CBase a;
     Cchild b;
     a.set_data1(888);

     //public成员可以这样访问
     cout<<a.m_data2<<endl;
     //而私有成员无法这样访问
     //cout<<a.m_data1<<endl;//错误

     //但可以这样访问私有成员
     cout<<*((int*)&a+2)<<endl;


     //在继承类中,一般的函数(非虚函数)被同名函数所隐藏,而并没有覆盖他,
     b.func2();//我们直接调用func2得到的是Cchild中的func2
     b.CBase::func2();//这样我们可以把隐藏的fun2唤出

     //要访问b中从CBase继承而来的私有虚函数vfun1;
     cout<<"虚函数表的地址指针"<<(int*)(&b)<<endl;
     cout<<"虚函数表的地址"<<(int*)*((int*)(&b))<<endl;
     cout<<"第一个虚函数的地址"<<((int*)*((int*)(&b))+0)<<endl;
     cout<<"第二个虚函数的地址"<<((int*)*((int*)(&b))+1)<<endl;
     cout<<"第三个虚函数的地址"<<((int*)*((int*)(&b))+1)<<endl;
    
     typedef void(*PFun)();//定义函数指针类型
       PFun fun1;
     fun1=(PFun)*((int*)*((int*)(&b))+0);
     fun1();//CBase::vfun1;成功访问了私有的虚函数
     ((PFun)*((int*)*((int*)(&b))+0))();//和上面的效果是一样的.
     (((PFun)*((int*)*((int*)(&b))+0)))();//访问第二虚函数个函数注意是Cchild::vfun2(),而不是CBase::vfun2(),
                                           //在b中Cbase::vfun2已经被Cchild::vfun2所覆盖。

运行效果如图所示
.总结发成下面的图


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值