2013-01-04 32 views
-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(); 
} 

這裏是如何使用朋友函數訪問私有變量的示例如何使用而不使用朋友函數?如何在C++中使用朋友函數訪問私有變量

+6

究竟爲什麼你需要做到這一點? – chris

+6

添加公共getter/setter! –

+0

請參閱http://bloglitb.blogspot.ro/2010/07/access-to-private-members-thats-easy。HTML –

回答

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); 
+0

沒有如果有一個可靠的方式來做到這一點,而不使用'friend'使用公共的訪問也 –

+0

@ user1670364,爲什麼會在C++語言的設計者首先介紹'friend'?你可以使用偏移量和指針(請參閱其他答案),但最終你需要獲得一個隱藏的* private *變量的偏移量。如果沒有'朋友'或公共訪問器就可以得到它,變量將不再是私有的。 – dasblinkenlight

+3

其實,有一個可靠的,合法的方式 - http://bloglitb.blogspot.ro/2010/07/access-to-private-members-thats-easy.html –

0
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++; } 
+0

我很欣賞即將推出的所有降薪活動;-) – queen3

+0

IMO建議可能不安全或不便攜或不良練習的代碼沒有任何問題,只要它被貼上標籤並解決OP的問題即可。讓買家當心! – Kevin

0

試試這個

ChangePrivate(sPoint); 

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

但它不是一個很好的編碼風格,只是爲了好玩。

的內部C++對象模型這本書給出了關於C++對象模型的詳細分析

+0

這是未定義的。 –

+0

@LuchianGrigore這就是爲什麼我說「只是爲了好玩」。但實際上它只是一個只有一個成員的簡單結構。所以這可能適用於大多數編譯器。 :) –

2

訪問控制不適用於參數明確模板實例([temp.explicit]/12)。這可以被利用來給私有成員公共接入(courtesy of 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(); 
} 
1

這裏是一個符合標準的黑客(source):

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; 
} 

Sample on ideone.

+0

爲什麼Point :: m_i的訪問可以成功? –