-1
#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();
}

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

4

5 回答 5

4

该关键字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);
于 2013-01-04T17:36:11.440 回答
2

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

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 上的样品。

于 2013-01-04T17:59:13.100 回答
2

访问控制不适用于显式模板实例化的参数 ( [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;
};

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

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();
}
于 2013-01-04T17:56:49.590 回答
1
 void ChangePrivate ( Point &i ) { *(int*)( ((char*)&i) + 0 ) += 1; }

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

或者类似的东西

struct HackPoint
{
  int m_i;
};

void ChangePrivate ( Point &i ) { ((HackPoint*)(void*)&i)->m_i++; }
于 2013-01-04T17:38:29.907 回答
0

尝试这个

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

代替

ChangePrivate(sPoint);

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

深入 C++ 对象模型 这本书详细分析了 C++ 对象模型

于 2013-01-04T17:41:40.993 回答