昨天,有位同事丟擲了乙個問題:
乙個class內有乙個private屬性的struct型別,然後他想做的事情是,在繼承該class的子類中復用這個型別,但是由於該類似的private屬性,編譯是不通過的。
因此就引入了乙個問題:如何突破class的private屬性限制——試圖破壞class的封裝性,有點「逆天而行」的感覺。
查了一下,方法確實是有的。
假設有以下類:
m_nprivate
class x
templatevoid func(const t &t)
{} const
int getvalue()
};
void *p = &x; // 獲取類的起始位址,其實也就是m_nprivate資料成員的位址
int *n = (int *)p;
int tmp = 2;
*n = tmp; // 改寫其值
cout
<< x.getvalue() << endl; // 輸出為2
這種方法的缺點:計算偏移量是個麻煩的事情,涉及到記憶體對齊、編譯器版本等,可移植性低,而且這種方法只能訪問成員變數,卻不能達到「使用private內建型別」的目的。
在類x的定義前,加一句:
#define
private
public
該方法可以欺騙編譯器,讓它把「private」當作「public」。
然而它有兩個違背標準的行為:
1)#define 保留字是非法的
2)違反了唯一定義規則(odr,one definition rule),然而類的底層記憶體布局沒改變,故可行
m_nnotprivate
// 同x的記憶體布局,將變數or型別定義改為public
class y ;
void func(x* xptr)
首先我們將x型別的指標轉換為y型別的指標,在編譯器看來,我們訪問的是y型別的public成員m_nnotprivate,因此編譯通過,然而事實上該指標是x型別的,由於y跟x的記憶體布局是完全一樣,因此訪問y的m_nnotprivate成員實際上也就是在訪問x的m_nprivate成員。
類似的方法就是,在y中增加乙個非虛成員函式,該函式用來返回m_nprivate的位址。
類似以上方法,不過是通過新增友元宣告來訪問的~
如果x中存在乙個成員模版,那麼可以這樣子:
namespace;}
template
<>
void x::func(const y&) //特化
void test()
這種方法利用了x具有乙個成員模板的事實,通過特化函式模版,來打入敵人內部。**完全符合標準,標準也確保這種行為會按照編碼者的意圖行事。boost和loki中大量運用此手法。
以上方法參考:
C 突破private訪問許可權的黑科技
如何突破class的private屬性限制 試圖破壞class的封裝性,有點 逆天而行 的感覺。includeusing namespace std class x templatevoid func const t t const int getvalue friend void func x x...
突破訪問許可權
我們在寫 的時候,按約定都是把成員資料放到private訪問區中,然後在通過相應的函式來訪問。那又有什麼樣的 可以突破訪問許可權來直接操作類中private區段中的成員資料呢?首先,我們想到了指標,對吧 指標可是萬能之王,然而也是萬惡之源。那我們就先來看看指標如何突破馬其諾防線的。先定義乙個測試類 ...
建構函式 訪問許可權private
一 建構函式 具有建構函式的類會在每次建立新物件時先呼叫此方法,所以非常適合在使用物件之前做一些初始化工作。如果子類中定義了建構函式則不會隱式呼叫其父類的建構函式。要執行父類的建構函式,需要在子類的建構函式中呼叫parent construct 如果子類沒有定義建構函式則會如同乙個普通的類方法一樣從...