幾種直接訪問類的私有變量的方法 咱們知道在C++中,爲了防止某些數據成員或成員函數從外部被直接訪問,能夠將它們聲明爲private,這樣編譯器會阻止任何來自外部非友元的直接訪問。ios
那麼咱們真的就沒辦法直接修改類的私有數據成員了嗎?數組
來看一段代碼:ide
1 #include <iostream>
2 using namespace std;
3
4
5 class A
6 {
7 private:
8 // a & b are private members of class A
9 int a;
10 double b;
11 public:
12 // initialize a & b as value 0
13 A() : a(0), b(0) {}
14
15 public:
16 // for display the value of a & b
17 int GetA();
18 double GetB();
19 };
20
21 int A::GetA()
22 {
23 return a;
24 }
25
26 double A::GetB()
27 {
28 return b;
29 }
30
31 int _tmain(int argc, _TCHAR* argv[])
32 {
33 A test;
34
35 cout < < "before pointer access:\n"
36 < < " test.a = " < < test.GetA() < < "\n"
37 < < " test.b = " < < test.GetB() < < "\n" < < endl;
38
39 // access object test of class A by pointer
40 int* privateA = reinterpret_cast <int*>(&Test);
41 double* privateB = reinterpret_cast <double*>(&Test) + 1;
42
43 // value changing by pointer!
44 *privateA = 1;
45 *privateB = 2.5;
46
47 cout < < "after pointer access:\n"
48 < < " test.a = " < < test.GetA() < < "\n"
49 < < " test.b = " < < test.GetB() < < "\n" < < endl;
50
51 return 0;
52 }
53函數
運行後輸出結果爲:
before pointer access:
test.a = 0
test.b = 0spa
after pointer access:
test.a = 1
test.b = 2.5指針
能夠看到,雖然咱們已經將 A::a 和 A::b聲明爲 private ,但在強大的指針面前,類的任何細節都暴露無遺。對象
某種程度上,類的一個對象能夠看做包含不一樣類型元素的數組,其數據成員的地址偏移由數據成員在類定義中的順序決定——類對象的地址指向類中第一個被定義的數據成員的地址;第二個被定義的數據成員的地址取決於第一個數據成員的類型,若第一個爲 int 型,則再偏移 4 個字節( sizeof(int) )即獲得第二個數據成員的地址(有時也不必定是這樣,如上例中,因爲類型對齊的緣故,實際偏移 8 個字節( sizeof(double) )才獲得第二個數據成員的地址,具體內容不在本文討論範圍內)。編譯器
因此即便你將其餘全部細節都隱藏在 cpp 中,但頭文件中不可避免地會出現私有數據成員的聲明。而類的其餘用戶只要能看到這個聲明,就能推算出類中各數據成員的相對地址偏移,從而用指針輕鬆實現對私有成員的訪問。it
上例只對私有數據成員進行了驗證,有興趣的能夠試試看用函數指針可否訪問私有成員函數。io
還有幾種很巧妙的方法:
介紹一下:
第一指針,上面已經說了。。
第二,使用define
用一個C++的小例子來講明怎樣使用#define來訪問類的私有成員。con_all"> 咱們知道,類的私有成員在類的外部是不能被訪問的。
例若有下面的這個簡單的類: class ClxECS
{
private:
int iPrivate;
}; 那麼下面的這個函數是不能經過編譯的: void ECS_test()
{
ClxECS lx;
lx.iPrivate = 13;
cout < < lx.iPrivate < < endl;
} 可是,咱們並非沒有辦法來訪問類的私有成員。
其實,方法很簡單,只要在類的聲明前面加上以下一行代碼就好了: #define private public 一樣的,這個方法對保護成員也適用: #define protected public 可是,這是一個非正規的手段,它將破壞類的全部封裝性。而C++中的#define的存在也是爲了跟C兼容。因此只有在很是特殊的狀況下,纔會用這種非正規方法訪問類的私有或保護成員。
第三,使用友元
————————————————————————————————————
而在C#中咱們能夠用反射的方式去訪問類的私有成員。