最近在開源代碼中發(fā)現(xiàn)了一種不修改代碼的情況下, 訪問庫中的類的私有成員變量的方法. 我們知道, 一個類的成員變量設(shè)置成private, 外部函數(shù)一般通過友元才能訪問. 但是庫已經(jīng)寫好了, 在不修改庫的代碼, 為其添加友元的情況下, 也可以使用一些特殊技巧訪問類的私有成員.
為了介紹這個方法, 首先介紹一些C++中的特性, 如下.
指向成員的指針(pointer to member variable)
C++中可以定義指向類成員變量的指針類型. 這個成員變量可以不是static的.
#include <iostream>
using namespace std;
class Car {
public:
int speed;
};
int main() {
//定義一個指向成員speed的指針, 用成員的地址初始化.
int Car::*pSpeed = &Car::speed;
Car c1;
c1.speed = 1; // direct access
cout << "speed is " << c1.speed << endl;
//已經(jīng)有一個類的時候, 可以通過這個指針來訪問類的成員.對于任意不同的類都可
//以這么干.
c1.*pSpeed = 2; // access via pointer to member
cout << "speed is " << c1.speed << endl;
return 0;
}
從上面的帶注釋的例子可以看出, 這里的指針和常見的表示具體地址的指針是不一樣的. 這樣, 我們要訪問一個類的成員變量, 除了通過"."訪問, 還可以定義指針來訪問.
模板顯式實例化(template Explicit instantiation)
我們知道, 對于類模板來說, 我們提供模板參數(shù)可以實例化一個模板類. 除了這種方法以外, 模板還可以使用顯式實例化, 在顯式實例化的時候, 會忽略參數(shù)的private屬性.
所以到此, 訪問的方法就比較清晰了. 我們可以定義一個指針來指向類的私有成員, 但是由于成員是私有的, 直接賦值不會成功, 所以我們可以利用模板參數(shù)的方式完成賦值, 通過顯式實例化來忽略private修飾符.
一個訪問私有成員的例子
介紹完了基礎(chǔ)知識, 接下來看一個例子. 我們在例子中定義了一個類FortKnox, 里面有一個private成員 value. 這個類是別人寫的, 設(shè)置private為了讓別人不能直接訪問, 并且編譯到了動態(tài)庫里面. 但是利用上面介紹的方法, 我們可以偷偷使用類里面的private變量.
#include<iostream>
using namespace std;
typedef int value_type;
//定義了一個類,里面有一個private成員,我們不希望別人直接訪問
struct FortKnox {
FortKnox() : value(0) {}
private:
value_type value;
};
//這是一個指向類的成員變量的指針類型
typedef value_type FortKnox::* stolen_mem_ptr;
//模板定義一個友元函數(shù),返回指向類的成員變量的指針.
template<stolen_mem_ptr MemPtr>
struct Robber {
friend stolen_mem_ptr steal() {
return MemPtr;
}
};
//模板顯式初始化, 可以忽略private修飾符, 這樣我們的友元函數(shù)就可以
//獲得指向成員的指針,并且忽略了private
template struct Robber<&FortKnox::value>;
stolen_mem_ptr steal();
int main() {
FortKnox f;
//返回指向成員的指針,忽略了private修飾符
auto accessor = steal();
//訪問私有成員
cout<<f.*accessor<<endl;
f.*accessor=1;
cout<<f.*accessor<<endl;
return 0;
}
總結(jié)
這個特性平時應(yīng)該比較少用到, 既然碰到了, 就記錄一下.
相關(guān)文獻(xiàn)
[1] http://bloglitb.blogspot.de/2011/12/access-to-private-members-safer.html
[2] http://stackoverflow.com/questions/670734/c-pointer-to-class-data-member
[3] http://stackoverflow.com/questions/15110526/allowing-access-to-private-members
原始鏈接:yiwenshao.github.io/2017/01/16/如何用C-偷私有變量/
文章作者:Yiwen Shao
許可協(xié)議:** Attribution-NonCommercial 4.0
轉(zhuǎn)載請保留以上信息, 謝謝!