原則上,C++類中私人變數不允許在類之外的其他任何地方訪問,一般來說功能完善的類都會提供get,set方法來操作類屬性值,還有就是就是通過友元訪問。但是!但如果沒有get、set方法都沒有提供,也沒有定義友元,比如使用的是第三方提供的.o(或者動態庫)來進行開發的,並且實際應用中我們確確實實需要改變其中某個對象的一個私人參數,有沒有什麼辦法呢?還有一種比較文藝青年的方法,我們知道,一個進程有程式段和資料區段,如果我們知道了對象的資料空間,那麼得到該對象的成員變數值也就很簡單了,而實際上,對象資料區段的首地址其實就是對象地址,以例子說明:
方法1:普通青年
友元方法:
#include<iostream.h>class A{int t;public:A(){t=2002;//在建構函式中初始化成員變數t}friend class B;//聲明友元類classB};class B{public:A a;int sum(){return a.t+1500;//友員class B訪問class A中的私人成員變數t}};void main(){B b;cout<<b.sum()<<endl;}
方法2:文藝青年
記憶體位址操作法
我們知道,C++編譯器將資料和程式段分開,所有的類變數會按照聲明順序依次存入資料區段,所以,如果知道了第一個變數的地址,那麼後面的地址也就依次累加即可逐一求出了。有了變數地址,那麼也就可以對它的值進行修改了。還是以上面的例子來說明,一下程式編寫了如何更改類成員b的值:
#include <iostream>#include <string>using namespace std;class center{public:void setX(float _x){x=_x;}void setY(float _y){y=_y;}void setMeanValue(float avg){meanValue=avg;}float getX(){return x;}float getY(){return y;}float getMeanValue(){return meanValue;}center():x(0.0),y(0.0),meanValue(0.0){}private:float x;float y;float meanValue;};int main(){center A;//普通青年的賦值方法;A.setX(1.0);A.setY(4.0);A.setMeanValue(13.0);cout<<A.getX()<<" "<<A.getY()<<" "<<A.getMeanValue()<<endl;//文藝青年的賦值方法;//*((float*)&A):將center對象A的記憶體空間強制類型轉化為用int*指向的記憶體空間,訪問該記憶體float tmp = *((float*)&A);cout<<tmp<<endl;//輸出A.x的值tmp = *((float*)&A + 1);cout<<tmp<<endl;//輸出A.y的值*((float*)&A + 2)=2;//修改A.meanValue的值cout<<A.getMeanValue()<<endl;}
你也可以通過友元的記憶體位址來操作,即通過class B 的記憶體位址訪問 class A的私人成員。
此外,另附一篇與此類似的文章,也很有啟發性。
剖析器員和駭客的區別
題目:
設有如下C++類
class A{ int value;public: A(int n = 0) : value(n) {} int GetValue() { return value; }};
請使用某種方式來在類的外部改變私人成員A::value的值。
程式員的可能做法:
class A{ int value;public: A(int n = 0) : value(n) {} int GetValue() { return value; } void SetValue(int n) { value = n; }};void f(){ A a; a.SetValue(5);}
駭客的可能做法:
void f(){ A a; *((int *)&a) = 5;}
結論:
程式員習慣於遵循既有的限制來增加既有的東西。
駭客習慣於利用既有的東西來打破既有的限制。