類的乙個特徵就是資料與方法封裝在一起,在編譯器越來越智慧型的今天,大多數程式設計師已經習慣了資料與方法「本來」就是乙個「整體」的概念。事實是不是這樣呢?在物件導向語言出現之前的程式世界又是什麼樣的呢?讓我們先回到c的世界中,看看那裡的資料與方法(c中稱為函式)是什麼樣子的。
在c中通常定義乙個結構體用來把一些資料組合在一塊兒,然後定義乙個函式處理這個結構體。例如:
/* 版本1:*/
typedef
struct _sampledata
sampledata;
/*函式定義,列印sampledata結構的資料*/
void processdata()
可以看到資料與對資料的操作是分離的,只要把資料所在的檔案包含進來,就可以任意定義乙個函式來進行操作。
接著再看看用c++ 把資料與方法封裝在一起的**形式。
//c++
版本class sampledata ;
~sampledata(){};
void processdata() ;
c++ 可以把資料和對資料的操作整合到乙個class 中。能否在c的 struct 中做到跟c++的 class 一樣,把processdata() 與 資料變數整合在一起呢?模仿上面的類定義,我們可能會嘗試定義乙個這樣的資料結構:
/* 版本2:*/
struct _sampledata
而processdata() 函式的實現依然跟【版本1】一樣。編譯,鏈結。真好,沒有出現任何的錯誤。是否這樣就可以了呢?噢,忘記了乙個重要的步驟,還沒有在任何地方使用過這個sampledata結構體的processdata 操作呢。ok, 沒有關係,在主函式宣告呼叫一下吧。大概像下面這樣:
void main()
再編譯,通過。鏈結,出現錯誤:unresolved external symbol "public: void __thiscall _sampledata::processdata(void)" (?processdata@_sampledata@@qaexxz)。編譯器找不到結構體中宣告的processdata 函式的具體實現,看來現在這樣呼叫data.processdata() 是不行的。編譯器並沒有我們想象的那樣自動地把 processdata 的宣告與它的實現對應起來。那麼怎樣做才能達到預先的目的呢?
如果能把processdata()函式的位址賦給 sampledata 結構裡的操作宣告,那麼一切問題都解決了。看來【版本2】也需要改進一下。
/* 版本3:*/
typedef
struct _sampledata
sampledata;
主函式也得改一下,在使用data.processdata() 之前,把函式processdata的位址賦給結構體裡的函式指標變數。結果如下:
void main()
再編譯、鏈結,終於通過。
到這裡你已經認為這樣成功的實現了上面定義的sampledata的c++ 版本。不過不要高興的太早,做個測試看看。
void main()
按預先的設想,執行完step 4 後應該列印出這樣的結果:data1=22, data2=987654321
而實際上列印出的是:data1=12, data2=123456789 。原因很明顯,processdata 函式裡面有個 sampledata的區域性變數。也就是說,結構體裡的方法data.processdata() 列印出的內容並不是結構體本身的變數,而是這個區域性變數的內容。
那怎樣才能列印出結構體內變數的內容呢?c++裡編譯器為類的方法加上了 this 指標,所以我們不用去擔心這個問題。而在c的世界裡,編譯器並沒有這樣做。那麼就需要顯示的增加乙個結構指標,代替c++中類似this指標的功能。接下來再改變一下sampledata結構體的定義:
/* 版本4:*/
typedef
struct _sampledata
sampledata;
函式的實現也需要修改,它看起來像下面這個樣子:
void processdata(
struct _sampledata * thissample)
接著在主函式的呼叫方式也要修改:
data.processdata(&data);
//傳入data變數的位址。
看看執行結果,ok,這才是我們所想要的功能。而 thissample這個指向自己的指標就是c++裡this指標的實現形式,只不過在c裡要自己實現,而在c++是編譯器自動為我們加上了,看到這裡你也應該已經理解c++的this指標的概念了吧。
看來在機器的世界裡資料與對資料的操作是分開的,只是由於在編譯器的支援下,才給程式設計師展現出了乙個完美的物件。
**:
c語言資料封裝
最近寫了乙個linux 下tcp聊天室程式,剛開始時是寫在乙個檔案裡的版本,後來整理了思路寫在了不同的檔案裡,於是考慮程式間的呼叫關係,引數傳遞,介面之類的問題,發展到最後考慮的是資料完全的封裝。比如在test.c中定義 include stu.h struct stu struct stu stu...
用C語言封裝Windows程式
為了使windows sdk程式結構更為清晰,可利用c 函式把程式模組化的特定,對windows程式進行封裝。例如,用c語言編寫在滑鼠左鍵按下時,可在視窗的使用者區顯示乙個字串 hello world!的windows程式。選擇 file c source file 命名為 op.c,如下 incl...
資料封裝和處理 C語言
資料封裝和處理 c語言 c語言,面向過程,最核心的就是資料處理。有時我們需要處理的資料量很大,而且資料型別也不一,那有沒有一種方法可以讓這些資料被統一呼叫和處理呢?有的,那就是封裝這些資料。將 資料處理 抽象出來,無非就是資料定義,資料的值,資料處理這三個東西,那麼我們可以定義乙個結構體,這個結構體...