-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によって課されるアクセス制限をバイパスするために特にあります。privateprotected

を使用せずにプライベート変数にアクセスする場合は、クラス自体にパブリック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

アクセス制御は、明示的なテンプレートのインスタンス化()への引数には適用されません[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 に答える
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;
}

イデオンのサンプル。

于 2013-01-04T17:59:13.100 に答える
1
 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++; }
于 2013-01-04T17:38:29.907 に答える
0

これを試して

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

それ以外の

ChangePrivate(sPoint);

しかし、それはただの楽しみのために、良いコーディングスタイルではありません。

C ++オブジェクトモデルの内部 この本は、C++オブジェクトモデルに関する詳細な分析を提供します

于 2013-01-04T17:41:40.993 に答える