深入解析C++編程中類的封裝特性
共用接口和私有實(shí)現(xiàn)的分離
C++通過類來實(shí)現(xiàn)封裝性,把數(shù)據(jù)和與這些數(shù)據(jù)有關(guān)的操作封裝在一個(gè)類中,或者說,類的作用是把數(shù)據(jù)和算法封裝在用戶聲明的抽象數(shù)據(jù)類型中。
實(shí)際上用戶往往并不關(guān)心類的內(nèi)部是如何實(shí)現(xiàn)的,而只需知道調(diào)用哪個(gè)函數(shù)會得到什么結(jié)果,能實(shí)現(xiàn)什么功能即可。
在聲明了一個(gè)類以后,用戶主要是通過調(diào)用公用的成員函數(shù)來實(shí)現(xiàn)類提供的功能(例如對數(shù)據(jù)成員設(shè)置值,顯示數(shù)據(jù)成員的值,對數(shù)據(jù)進(jìn)行加工等)。因此,公用成員函數(shù)是用戶使用類的公用接口(public interface),或者說是類的對外接口。
類中被操作的數(shù)據(jù)是私有的,實(shí)現(xiàn)的細(xì)節(jié)對用戶是隱蔽的,這種實(shí)現(xiàn)稱為私有實(shí)現(xiàn)(private implementation)。這種“類的公用接口與私有實(shí)現(xiàn)的分離”形成了信息隱蔽。
軟件工程的一個(gè)最基本的原則就是將接口與實(shí)現(xiàn)分離,信息隱蔽是軟件工程中一個(gè)非常重要的概念。它的好處在于:
如果想修改或擴(kuò)充類的功能,只需修改本類中有關(guān)的數(shù)據(jù)成員和與它有關(guān)的成員函數(shù),程序中類外的部分可以不必修改。
如果在編譯時(shí)發(fā)現(xiàn)類中的數(shù)據(jù)讀寫有錯(cuò),不必檢查整個(gè)程序,只需檢查本類中訪問這些數(shù)據(jù)的少數(shù)成員函數(shù)。
類聲明和成員函數(shù)的分離
在面向?qū)ο蟮某绦蜷_發(fā)中,一般做法是將類的聲明(其中包含成員函數(shù)的聲明)放在指定的頭文件中,用戶如果想用該類,只要把有關(guān)的頭文件包含進(jìn)來即可。
由于在頭文件中包含了類的聲明,因此在程序中就可以用該類來定義對象。由于在類體中包含了對成員函數(shù)的聲明,在程序中就可以調(diào)用這些對象的公用成員函數(shù)。
為了實(shí)現(xiàn)上一節(jié)所敘述的信息隱蔽,對類成員函數(shù)的定義一般不放在頭文件中,而另外放在一個(gè)文件中。
例如,可以分別寫兩個(gè)文件:
student.h頭文件
//這是student.h頭文件,在此文件中進(jìn)行類的聲明
class Student //類聲明
{
public :
void display( );//公用成員函數(shù)原型聲明
private :
int num;
char name[20];
char sex;
};
student.cpp
// 在此文件中進(jìn)行函數(shù)的定義
#include <iostream>
#include "student.h"http://不要漏寫此行,否則編譯通不過
void Student::display()//在類外定義display類函數(shù)
{
cout<<"num:"<<num<<endl;
cout<<"name:"<<name<<endl;
cout<<"sex:"<<sex<<endl;
}
為了組成一個(gè)完整的源程序,還應(yīng)當(dāng)有包括主函數(shù)的源文件(main.cpp):
// 主函數(shù)模塊
#include <iostream>
#include ″student.h″ //將類聲明頭文件包含進(jìn)來
int main( )
{
Student stud; //定義對象
stud.display( ); //執(zhí)行stud對象的display函數(shù)
return 0;
}
這是一個(gè)包括3個(gè)文件的程序,組成兩個(gè)文件模塊:一個(gè)是主模塊main.cpp,一個(gè)是student.cpp。在主模塊中又包含頭文件student.h。在預(yù)編譯時(shí)會將頭文件student.h中的內(nèi)容取代#include ″student.h″行。
請注意,由于將頭文件student.h放在用戶當(dāng)前目錄中,因此在文件名兩側(cè)用雙撇號包起來(″student.h″)而不用尖括號(<student.h>),否則編譯時(shí)會找不到此文件。
使用C++編譯系統(tǒng)對兩個(gè)源文件main.cpp和student.cpp分別進(jìn)行編譯,得到兩個(gè)目標(biāo)程序main.obj和student.obj,然后將它們和其他系統(tǒng)資海連接起來,形成可執(zhí)行文件main.exe,見圖 。
注意,目標(biāo)文件的后綴在不同的C++編譯系統(tǒng)中是不同的,例如在GCC中,后綴是 .o,這里使用 .obj 是對VC 6.0而言。
在運(yùn)行程序時(shí)調(diào)用stud中的display函數(shù),輸出各數(shù)據(jù)成員的值。
有的讀者可能會考慮這樣一個(gè)問題:如果一個(gè)類聲明多次被不同的程序所調(diào)用,每次都要對包含成員函數(shù)定義的源文件(如上面的student.cpp進(jìn)行編譯,這是否可以改進(jìn)呢?的確,可以不必每次都對它重復(fù)進(jìn)行編譯,而只需編譯一次即可。把第一次編譯后所形成的目標(biāo)文件保存起來,以后在需要時(shí)把它調(diào)出來直接與程序的目標(biāo)文件相連接即可。 這和使用函數(shù)庫中的函數(shù)是類似的。
這也是把成員函數(shù)的定義不放在頭文件中的一個(gè)好處。如果對成員函數(shù)的定義也放在類聲明的頭文件中,那么在對使用這些類的每一個(gè)程序的每一次編譯時(shí)都必然包括對成員函數(shù)定義的編譯,即同一個(gè)成員函數(shù)的定義會多次被重復(fù)編譯。只有把對成員函數(shù)的定義單獨(dú)放在另一文件中,才能做到單獨(dú)編譯。
在實(shí)際工作中,并不是將一個(gè)類聲明做成一個(gè)頭文件,而是將若干個(gè)常用的功能相近的類聲明集中在一起,形成類庫。
類庫有兩種:一種是C++編譯系統(tǒng)提供的標(biāo)準(zhǔn)類庫;—種是用戶根據(jù)自已的需要做成的用戶類庫,提供給自己和自己授權(quán)的人使用,這稱為自 定義類庫。在程序開發(fā)工作中,類庫是很有用的,它可以減少用戶自己對類和成員函數(shù)進(jìn)行定義的工作量。
類庫包括兩個(gè)組成部分:類聲明頭文件;已經(jīng)過編譯的成員函數(shù)的定義,它是目標(biāo)文件。
用戶只需把類庫裝入到自己的計(jì)算機(jī)系統(tǒng)中(一般裝到C++編譯系統(tǒng)所在的子目錄下),并在程序中用#include命令行將有關(guān)的類聲明的頭文件包含到程序中,就可以使用這些類和其中的成員函數(shù),順利地運(yùn)行程序。這和在程序中使用C++系統(tǒng)提供的標(biāo)準(zhǔn)函數(shù)的方法是一樣的,例如用戶在調(diào)用sin函數(shù)時(shí)只需將包含聲明此函數(shù)的頭文件包含到程序中,即可調(diào)用該庫函數(shù),而不必了解sin函數(shù)是怎么實(shí)現(xiàn)的(函數(shù)值是怎樣計(jì)算出來的)。
當(dāng)然,前提是系統(tǒng)已裝了標(biāo)準(zhǔn)函數(shù)庫。在用戶源文件經(jīng)過編譯后,與系統(tǒng)庫(是目標(biāo)文件)相連接。
在用戶程序中包含類聲明頭文件,類聲明頭文件就成為用戶使用類的公用接口,在頭文件的類體中還提供了成員函數(shù)的函數(shù)原型聲明,用戶只有通過頭文件才能使用有關(guān)的類。用戶看得見和接觸到的是這個(gè)頭文件,任何要使用這個(gè)類的用戶只需包含這個(gè)頭文件即可。包含成員函數(shù)定義的文件就是類的實(shí)現(xiàn)。
請?zhí)貏e注意,類聲明和函數(shù)定義一般是分別放在兩個(gè)文本中的。由于要求接口與實(shí)現(xiàn)分離,為軟件開發(fā)商向用戶提供類庫創(chuàng)造了很好的條件。
開發(fā)商把用戶所需的各種類的聲明按類放在不同的頭文件中,同時(shí)對包含成員函數(shù)定義的源文件進(jìn)行編譯,得到成員函數(shù)定義的目標(biāo)代碼。軟件商向用戶提供這些頭文件和類的實(shí)現(xiàn)的目標(biāo)代碼(不提供函數(shù)定義的源代碼)。用戶在使用類庫中的類時(shí),只需將有關(guān)頭文件包含到自己的程序中,并且在編譯后連接成員函數(shù)定義的目標(biāo)代碼即可。
由于類庫的出現(xiàn),用戶可以像使用零件一樣方便地使用在實(shí)踐中積累的通用的或?qū)S玫念?,這就大大減少了程序設(shè)計(jì)的工作量,有效地提高了工作效率。
您可能感興趣的文章
- 04-02c語言沒有round函數(shù) round c語言
- 01-10深入理解約瑟夫環(huán)的數(shù)學(xué)優(yōu)化方法
- 01-10深入二叉樹兩個(gè)結(jié)點(diǎn)的最低共同父結(jié)點(diǎn)的詳解
- 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)- 解析最少換車次數(shù)的問題詳解
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10深入Main函數(shù)中的參數(shù)argc,argv的使用詳解
- 01-10深入第K大數(shù)問題以及算法概要的詳解
- 01-10深入解析最長公共子串
- 01-10c++中inline的用法分析


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 01-10C#中split用法實(shí)例總結(jié)
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 08-05織夢dedecms什么時(shí)候用欄目交叉功能?
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 04-02jquery與jsp,用jquery
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 01-10delphi制作wav文件的方法


