C++突破private访问权限

转自:http://blog.csdn.net/jiange_zh/article/details/52191144

假设有以下类:

m_nPrivate
class X
{
private:
    int m_nPrivate;
​
public:
    X()
        : m_nPrivate(1)
    {}
​
    template<typename T>
    void Func(const T &t)
    {}
​
    const int GetValue()
    {
        return m_nPrivate;
    }
};

方法1:使用指针

void *p = &x;        // 获取类的起始地址,其实也就是m_nPrivate数据成员的地址
int *n = (int *)p;
​
int tmp = 2;        
*n = tmp;            // 改写其值cout << x.GetValue() << endl; // 输出为2

这种方法的缺点:计算偏移量是个麻烦的事情,涉及到内存对齐、编译器版本等,可移植性低,而且这种方法只能访问成员变量,却不能达到“使用private内置类型”的目的。

方法2:使用宏

在类X的定义前,加一句:

#define private public

该方法可以欺骗编译器,让它把“private”当作“public”。

然而它有两个违背标准的行为:

1)#define 保留字是非法的

2)违反了唯一定义规则(ODR,One Definition Rule),然而类的底层内存布局没改变,故可行

方法3:使用指针类型转换——偷天换日

m_nNotPrivate
// 同X的内存布局,将变量or类型定义改为public
class Y            
{
public:
    int m_nNotPrivate;
};
​
void Func(X* xPtr)
{
    (reinterpret_cast<Y*>(xPtr))->m_nNotPrivate = 2;
}

首先我们将X类型的指针转换为Y类型的指针,在编译器看来,我们访问的是Y类型的public成员m_nNotPrivate,因此编译通过,然而事实上该指针是X类型的,由于Y跟X的内存布局是完全一样,因此访问Y的m_nNotPrivate成员实际上也就是在访问X的m_nPrivate成员。

类似的方法就是,在Y中增加一个非虚成员函数,该函数用来返回m_nPrivate的地址。

方法4:添加友元声明

类似以上方法,不过是通过添加友元声明来访问的~

方法5:利用模版合法钻空子

如果X中存在一个成员模版,那么可以这样子:

namespace
{
    struct Y{};
}
​
template<>
void X::Func(const Y&) //特化
{
    m_nPrivate = 2;
}
​
void Test()
{
    X x;
    cout << x.GetValue() << endl;
​
    x.Func(Y());
    cout << x.GetValue() << endl;
}

这种方法利用了X具有一个成员模板的事实,通过特化函数模版,来打入敌人内部。代码完全符合标准,标准也确保这种行为会按照编码者的意图行事。boost和loki中大量运用此手法。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值