标签搜索

目 录CONTENT

文章目录

C++突破private的方案.md

小小城
2021-08-22 / 0 评论 / 0 点赞 / 10 阅读 / 3,673 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-05-02,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

C++突破private的方案

@[toc]

方法一:调用公共成员函数

#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中大量运用此手法

0

评论区