如何在不使用 C++ 中的友元函数的情况下访问私有变量

how to access private variables with out using friend function in c++

本文关键字:函数 友元 情况下 变量 访问 C++      更新时间:2023-10-16
#include <iostream>
using namespace std;
class Point
    {
    friend void ChangePrivate( Point & );
    public:
    Point( void ) : m_i(0) {}
    void PrintPrivate( void ){cout << m_i << endl; }
private:
int m_i;
};
void ChangePrivate ( Point &i ) { i.m_i++; }
int main()
{
     Point sPoint;
     sPoint.PrintPrivate();
     ChangePrivate(sPoint);
    sPoint.PrintPrivate();
}

这是示例如何使用友元函数访问私有变量如何在不使用友元函数的情况下使用?

关键字friend专门用于绕过private施加的访问限制并protected访问控制。

如果您想在不使用 friend 的情况下访问私有变量,请将公共访问器添加到类本身:这是访问私有变量的最常见和最预期的方式:

class Point
{
public:
    Point( void ) : m_i(0) {}
    void PrintPrivate( void ){cout << m_i << endl; }
    int getI() {return m_i;}
    void setI(int _i) {m_i = _i;}
private:
    int m_i;
};
...
Point sPoint;
sPoint.setI(sPoint.getI()+1);

这是一个符合标准的黑客(来源(:

template<typename Tag, typename Tag::type M>
struct Rob { 
  friend typename Tag::type get(Tag) {
    return M;
  }
};
class Point
{
public:
    Point( void ) : m_i(0) {}
    void PrintPrivate( void ){cout << m_i << endl; }
private:
    int m_i;
};
struct Point_f { 
  typedef int Point::*type;
  friend type get(Point_f);
};
template struct Rob<Point_f, &Point::m_i>;
void ChangePrivate ( Point &i ) 
{  
    i.*get(Point_f()) = 4;
}

在 ideone 上采样。

访问控制不适用于显式模板实例化的参数 ( [temp.explicit]/12 (。这可以用来向私人成员提供公共访问权限(由 litb 提供(:

首先是一些设置代码:

template<typename Tag>
struct result {
  /* export it ... */
  typedef typename Tag::type type;
  static type ptr;
};
template<typename Tag>
typename result<Tag>::type result<Tag>::ptr;
template<typename Tag, typename Tag::type p>
struct rob : result<Tag> {
  /* fill it ... */
  struct filler {
    filler() { result<Tag>::ptr = p; }
  };
  static filler filler_obj;
};
template<typename Tag, typename Tag::type p>
typename rob<Tag, p>::filler rob<Tag, p>::filler_obj;

现在Point的定义:

class Point
{
public:
    Point() : m_i(0) {}
    void PrintPrivate(){cout << m_i << endl; }
private:
    int m_i;
};

现在通过显式实例化rob<Pointm_i, &Point::m_i>来填充result<Pointm_i>::ptr - 这是一个显式模板实例化,因此访问控制不适用:

struct Pointm_i { typedef int Point::*type; };
template class rob<Pointm_i, &Point::m_i>;

并访问私有成员:

void ChangePrivate ( Point &i ) { (i.*result<Pointm_i>::ptr)++; }
int main()
{
     Point sPoint;
     sPoint.PrintPrivate();
     ChangePrivate(sPoint);
     sPoint.PrintPrivate();
}
 void ChangePrivate ( Point &i ) { *(int*)( ((char*)&i) + 0 ) += 1; }

如果适用或自定义计算的偏移量,请将 0 替换为 offsetof((。

或类似的东西

struct HackPoint
{
  int m_i;
};
void ChangePrivate ( Point &i ) { ((HackPoint*)(void*)&i)->m_i++; }

试试这个

*(int*)(&sPoint) += 1;

而不是

ChangePrivate(sPoint);

但这不是一种好的编码风格,只是为了好玩。

C++对象模型内部 本书对对象模型进行了详细的分析C++