C++突破private的方案
文章目录
- C++突破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;
}
方法二:友元函数
#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;
//注意因为类当中刚好只有两个int类型的变量,如果有其他情况把指针后移对应大小即可
*ptr = 5;//指向a
*(ptr + 1) = 5;// 指向b
cout<<"pointer reset a="<<s.geta()<<endl;
cout<<"pointer reset b="<<s.getb()<<endl;
return 0;
}
方法四:指针的类型装换
- 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 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;
}
- 如果不对齐的话看下面一个实验
#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;
}
};
//外部Y类
class 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中大量运用此手法