如何突破类private的访问控制限制

如何突破类private的访问控制限制

类的访问控制权限如下:

访问 public protected private
同一个类 yes yes yes
派生类 yes yes no
外部及外部类类 yes no no

接下来主要说一下外部函数及外部类几种突破private访问权限的方法。

调用公共成员函数

#include <iostream>
using namespace std;
class X {
private:
    int a;
    int b;
public:
    X(): a(3), b(4){}
    int geta(){
        return a;
    }
    void seta(int x){
        a=x;
    }
    int getb(){
        return b;
    }
    void setb(int x){
        b=x;
    }
    friend int setgetbx(X &,int x);
};
int main()
{
    X s=X();
    cout<<"init a="<<s.geta()<<endl;
    cout<<"init b="<<s.getb()<<endl;
    s.seta(10);
    s.setb(10);
    cout<<"reset a="<<s.geta()<<endl;
    cout<<"reset b="<<s.getb()<<endl;
    return 0;
}

运行结果:
在这里插入图片描述

友元函数

友元函数一般放在类的开始或者结束位置,在类内声明+friend关键字,在类外定义

#include <iostream>
using namespace std;

class X {
private:
    int a;
    int b;
public:
    X(): a(3), b(4){}
    int geta(){
        return a;
    }
    int getb(){
        return b;
    }
    friend int setgetbx(X & x,int temp);				// 类内声明友元函数
};
int setgetbx(X & x,int temp){  							// 类外定义友元函数
    x.b+=temp;
    return x.b;
}
int main()
{
    X s=X();
    cout<<"init a="<<s.geta()<<endl;
    cout<<"init b="<<s.getb()<<endl;

    int newb=setgetbx(s,5);								//调用友元函数
    cout<<"reset b="<<newb<<endl;
    cout<<"reset b="<<s.getb()<<endl;
    return 0;
}

运行结果:
在这里插入图片描述

使用 指针与引用访问

#include <iostream>
using namespace std;
class X {
private:
    int a;
    int b;
public:
    X(): a(3), b(4){}
    int geta(){
        return a;
    }
    int getb(){
        return b;
    }
};

int main()
{
    X s=X();
    cout<<"init a="<<s.geta()<<endl;
    cout<<"init b="<<s.getb()<<endl;
    int *ptr=(int *)(&s);                          		 // 类指针
    cout<<"init a="<<*ptr<<endl;
    cout<<"init b="<<*(ptr+1)<<endl;
    *ptr=5;												//指向a
    *(ptr+1)=5;											// 指向b
    cout<<"pointer reset a="<<s.geta()<<endl;
    cout<<"pointer reset b="<<s.getb()<<endl;
    return 0;
}

运行结果:
在这里插入图片描述
这里需要注意,如果有虚函数的话,指针需要加+ *(ptr+1) *(ptr+2) 因为虚函数表是类内第一个位置。

指针的类型装换

#include <iostream>

using namespace std;

class X {
private:
    int a;
    int b;
public:
    X(): a(3), b(4){}
    int geta(){
        return a;
    }
    int getb(){
        return b;
    }
};

class Y
{
public:
    int a;			//与 X里面a对应
	int b;			//与 X里面b对应
};

void Func(X* xPtr)
{
	// reinterpret_cast 用于进行各种不同类型的指针之间、
	// 不同类型的引用之间以及指针和能容纳指针的整数类型之间的转换。
	(reinterpret_cast<Y*>(xPtr))->b = 2;
}

int main()
{
    X s=X();
    cout<<"init a="<<s.geta()<<endl;
    cout<<"init b="<<s.getb()<<endl;
    Func(&s);
    Func(&s);
    //cout<<"reinterpret_cast reset a="<<s.geta()<<endl;
    cout<<"reinterpret_cast reset b="<<s.getb()<<endl;
    return 0;
}

下面结果为类X与Y内存对齐的情况,即X与Y 里面的成员变量x.a x.b的位置一一对应:
在这里插入图片描述
如果不对齐的话看下面一个实验

#include <iostream>

using namespace std;

class X {
private:
    int a;
    int b;
public:
    X(): a(3), b(4){}
    int geta(){
        return a;
    }
    int getb(){
        return b;
    }
};

class Y
{
public:
	int b;
};

void Func(X* xPtr)
{
	// reinterpret_cast 用于进行各种不同类型的指针之间、
	// 不同类型的引用之间以及指针和能容纳指针的整数类型之间的转换。
	(reinterpret_cast<Y*>(xPtr))->b = 2;
}

int main()
{
    X s=X();
    cout<<"init a="<<s.geta()<<endl;
    cout<<"init b="<<s.getb()<<endl;
    Func(&s);												//attention
    cout<<"reinterpret_cast reset a="<<s.geta()<<endl;
    cout<<"reinterpret_cast reset b="<<s.getb()<<endl;
    return 0;
}

此时修改Y的b 但是确实修改X里面的a,这是因为 Y的b 与X的啊 在类内具有相同的内存位置,归根究低还是对指针与实际内存的操作:
在这里插入图片描述

利用模版合法

#include <iostream>

using namespace std;

class X {
private:
    int a;
    int b;
public:
    X(): a(3), b(4){}
    template<typename T>				//在X类内定义成员模板函数
	void Func(const T &t){}
    int geta(){
        return a;
    }
    int getb(){
        return b;
    }
};
class Y {}; 												//外部Y类
template<>
void X::Func(const Y&) //特化						//attention			
{
	a=2;
	b=8;
}
int main()
{
    X s=X();
    cout<<"init a="<<s.geta()<<endl;
    cout<<"init b="<<s.getb()<<endl;
    s.Func(Y());									//attention
    cout<<"template reset a="<<s.geta()<<endl;
    cout<<"template reset b="<<s.getb()<<endl;
    return 0;
}

运行结果:
这种方法利用了X具有一个成员模板的事实,通过特化函数模版,来打入敌人内部。代码完全符合标准,标准也确保这种行为会按照编码者的意图行事。boost和loki中大量运用此手法。
在这里插入图片描述
参考:http://www.luyixian.cn/news_show_37214.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章