徐曉蓉+李永軍
摘要:類和對(duì)象是面向?qū)ο蟪绦蛟O(shè)計(jì)中非常重要的概念,也是初學(xué)者不容易理解的概念之一,該文用類比的方法清楚地解釋了類和對(duì)象的概念,并在內(nèi)存層面對(duì)類和對(duì)象進(jìn)行了深入的剖析,使學(xué)生能更加清晰地理解什么是類,什么是對(duì)象,以及類和對(duì)象在內(nèi)存中的存儲(chǔ)形式。
關(guān)鍵詞:類和對(duì)象;數(shù)據(jù)和操作;方法;屬性和行為
中圖分類號(hào):TP312 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1009-3044(2017)35-0106-03
A Thorough Analysis of Class and Object in C ++ by Analogy
XU Xiao-rong1, LI Yong-jun2
(1.College of Computer Science and Technology, Hunan University of Arts and Science, Changde 415000, China;2.School of Physics and Electronics, Henan University, Kaifeng 475004, China)
Abstract: Class and object are very important concepts in the Object-Oriented Programming, and they are very difficult to be understood by the beginners. In this paper, the concepts of class and object are explained clearly by analogy, and class and object are analyzed in memory, so that students can more easily understand what the class is , what the object is, and how class and object are stored in memory.
Key words:classes and objects; data and operation;methods; properties and behaviors
1 背景
類和對(duì)象是C++等面向?qū)ο蟪绦蛟O(shè)計(jì)中最重要的兩個(gè)基本概念,但就作者多年教授這門課的經(jīng)驗(yàn)看,學(xué)生大多因?yàn)橛忻嫦蜻^(guò)程程序設(shè)計(jì)的基礎(chǔ),最初都很難清楚地理解面向?qū)ο蟪绦蛟O(shè)計(jì)中的類和對(duì)象這兩個(gè)概念,從而碰到問(wèn)題總是很容易想到面向過(guò)程而很難想到使用面向?qū)ο蟮姆椒▉?lái)解決問(wèn)題。本文通過(guò)類比法,對(duì)類和對(duì)象的定義進(jìn)行了對(duì)比、分析和解釋,并在內(nèi)存層面深入剖析了類和對(duì)象在內(nèi)存中的存在形式,有助于初學(xué)者更快、更準(zhǔn)確的理解類和對(duì)象的概念。
2 用類比法理解類和對(duì)象的定義
2.1 類的定義
數(shù)學(xué)上,所謂定義,即是對(duì)于一種事物的本質(zhì)特征的確切而簡(jiǎn)要的說(shuō)明;比如,質(zhì)數(shù)的定義:除了1和它本身以外不再有其他因數(shù)的大于1的自然數(shù)。
而在C++中,類的定義也是先找出類的特征,再給出類定義的描述,即必須首先對(duì)某類的若干對(duì)象進(jìn)行分析,總結(jié)出該類對(duì)象(所關(guān)注)靜態(tài)的屬性(或數(shù)據(jù))和動(dòng)態(tài)的方法(或行為、或操作),即特征,最后再使用關(guān)鍵詞class將所有屬性和方法整合起來(lái)來(lái)形成類的定義。
比如:通過(guò)對(duì)很多個(gè)人特征的分析發(fā)現(xiàn),對(duì)于人,通常關(guān)注的是姓名,性別,年齡等這些靜態(tài)的屬性,除此之外,人還有一些動(dòng)態(tài)的行為,比如會(huì)思考、會(huì)說(shuō)話、會(huì)微笑等等。當(dāng)總結(jié)出了人的靜態(tài)和動(dòng)態(tài)的特征之后,就可以定義什么是人!用 c++語(yǔ)言來(lái)描述出來(lái)就是如下程序段:
[例程1]
class Person
{private:
char name[20];
int age;
char sex;
public:
void think()
{ cout << "I am a person, and I can think!"< } void talk() { cout << "I am a person, and I can talk with you!" << endl; } void smile() { cout << "I am a person, and I like smiling!" << endl; } }; [例程1]中,class是C++中用來(lái)定義類的關(guān)鍵詞,而Person是定義的類的名字,類名可以由程序員自己定義。從[例程1]中可以看出,C++中動(dòng)態(tài)行為是用函數(shù)來(lái)表達(dá)的,稱為成員函數(shù),每一個(gè)成員函數(shù)都可以作為人與外界溝通交流的一個(gè)接口,所以,一般將成員函數(shù)定義成公有的(即public:)。而靜態(tài)的屬性,稱為數(shù)據(jù)成員,是用類型及屬性名來(lái)表示,一般是每個(gè)人所特有的,因此,一般將其定義為私有的(即private:)。當(dāng)然,每個(gè)類中有幾個(gè)成員函數(shù)以及它們的類型、參數(shù)及具體實(shí)現(xiàn)的功能需要程序員自己去按實(shí)際需要來(lái)定義與實(shí)現(xiàn),數(shù)據(jù)成員有幾個(gè)以及其名字、類型也是如此。 2.2 對(duì)象的定義 定義了類,相當(dāng)于定義了一種新的數(shù)據(jù)類型,與系統(tǒng)的基本數(shù)據(jù)類型相似。也就是說(shuō),在[例程1]中定義Person類之后,就可以像以前使用的int、double、float等一樣來(lái)使用Person了,只不過(guò),用系統(tǒng)的基本數(shù)據(jù)類型定義的變量,通常稱為變量,而用用戶自己定義的類型如Person定義的變量,通常稱之為對(duì)象而已,如:
int a; //a是變量,a中可以存放一個(gè)int型的數(shù)據(jù)。
Person p; //而p,則是對(duì)象,p中可以存放一個(gè)Person型的數(shù)據(jù)。
對(duì)象的定義格式為:類型 對(duì)象名;
2.3 類和對(duì)象的使用
類是抽象的,而對(duì)象則是具體的。類和對(duì)象的關(guān)系就好比人和某人張三的關(guān)系,人只是存在于我們的意念中,而張三這個(gè)人卻是實(shí)實(shí)在在存在與這個(gè)現(xiàn)實(shí)世界中的。張三具有人的所有屬性和行為。[例程1]中的Person類就是抽象的,要想使用Person類,必須定義Person類的對(duì)象,通過(guò)具體對(duì)象來(lái)使用類。如Person p; 定義了具體對(duì)象之后,就可以通過(guò)給對(duì)象發(fā)送指令來(lái)使用類,如p.smile();等。
3 類和對(duì)象的內(nèi)存
3.1 類的內(nèi)存
類是抽象的,因此,類的定義只是一種定義性說(shuō)明,類定義中的數(shù)據(jù)成員本身是不占內(nèi)存空間的,也就是說(shuō),類的內(nèi)存空間僅僅是定義類的那段代碼所占據(jù)的內(nèi)存空間。
3.2 對(duì)象的內(nèi)存
對(duì)象是具體的,具有類的所有屬性和行為。所以,理論上來(lái)說(shuō),對(duì)對(duì)象而言,它的屬性和行為都要占據(jù)內(nèi)存空間。
1) 普通類對(duì)象的內(nèi)存
定義Person類對(duì)象,Person p1,p2;那么,p1和p2對(duì)象的內(nèi)存示意圖如下圖1,圖2:
很顯然,對(duì)于同一個(gè)類的對(duì)象,每個(gè)對(duì)象中都有相同的成員函數(shù),這將造成內(nèi)存資源的極大浪費(fèi),因此,系統(tǒng)是將這些成員函數(shù)專門存儲(chǔ)在一個(gè)地方,每個(gè)對(duì)象的內(nèi)存中只存儲(chǔ)相應(yīng)的屬性,p1、p2的內(nèi)存狀態(tài)如圖3所示。從圖3中可以看出,每個(gè)對(duì)象在內(nèi)存中存儲(chǔ)的時(shí)候,只存儲(chǔ)屬于對(duì)象自己的數(shù)據(jù)成員,而沒(méi)有成員函數(shù)。對(duì)于不同對(duì)象如何使用存儲(chǔ)在同一個(gè)地方的相同成員函數(shù)在介紹this指針時(shí)再做解釋。
2) 派生類對(duì)象的內(nèi)存
[例程2]在上面[例程1]的Person類的基礎(chǔ)上派生出如下的Student類。
class Student :public Person
{
int num;
char major[30];
public:
void printMessage()
{cout <<"num:"< }}; 從理論上講,派生類具有基類的所有屬性和行為。如果有Student s; s對(duì)象的內(nèi)存狀態(tài)如圖4所示。由圖4可知,派生類對(duì)象的屬性具有兩類:基類的所有屬性、自己新增的屬性。但需注意,基類的屬性在派生類中是以無(wú)名對(duì)象(內(nèi)嵌對(duì)象用橢圓表示,以下類同。)的形式存在的, 所以,s對(duì)象的內(nèi)存示意如圖5所示。 3) 含虛基類的派生類對(duì)象的內(nèi)存 當(dāng)派生類的兩個(gè)基類有共同基類時(shí),在派生類對(duì)象中就會(huì)有兩個(gè)共同基類的對(duì)象,如[例程3]中的Derive類的對(duì)象。 [例程3] class Base { int b; public: Base(int x=0) { b=x; cout<<"&b="<<&b< } }; class Base1: public Base { int b1; public: Base1(int x=0,int y=0):Base(x) { b1=y; } }; class Base2: public Base { int b2; public: Base2(int x=0,int y=0):Base(x) { b2=y; } }; class Derive:public Base1,public Base2 { int c; public: Derive(int x,int y,int z): Base1(100,y),Base2(200,z) { c=z; } }; void main() { Derive d(3,2,1); } 這時(shí),在主函數(shù)中用Derive d(3,2,1)定義d對(duì)象之后,d的內(nèi)存狀態(tài)如圖6所示。很顯然,對(duì)象d中有兩個(gè)共同基類Base類的對(duì)象,這樣,會(huì)造成二義性。由于在Base類的構(gòu)造函數(shù)中加入了輸出b成員的地址,通過(guò)執(zhí)行程序,由圖7可以很明顯的看到,輸出了兩次b的地址,說(shuō)明,在d對(duì)象中,有兩個(gè)不同的Base類的對(duì)象。 為了消除這種二義性,c++中引入了虛基類,如[例程4]所示。 [例程4]該程序是在[例程3]的基礎(chǔ)上僅僅加了2個(gè)virtual和一個(gè)Base(300) class Base { int b; public: Base(int x=0) { b=x; cout<<"&b="<<&b< } }; class Base1: virtual public Base { int b1; public: Base1(int x=0,int y=0):Base(x)
{ b1=y; }
};
class Base2: virtual public Base
{
int b2;
public:
Base2(int x=0,int y=0):Base(x)
{ b2=y; }
};
class Derive:public Base1,public Base2
{
int c;
public:
Derive(int x,int y,int z): Base(300),Base1(100,y),Base2(200,z)
{ c=z; }
};
void main()
{
Derive d(3,2,1);
}
d對(duì)象的內(nèi)存狀態(tài)如圖9所示,雖然,從內(nèi)存看好似還是有兩個(gè)共同基類Base類的對(duì)象,但此時(shí),這兩個(gè)對(duì)象的b的值已經(jīng)是相同的,且是派生類Derive的構(gòu)造函數(shù)提供的值,而且程序執(zhí)行結(jié)果只輸出一個(gè)b的地址,如圖10所示。這說(shuō)明,此時(shí),在d對(duì)象中,已經(jīng)只有一個(gè)共同基類Base類的對(duì)象了,從而消除了二義性,由此,我們也可以得到d對(duì)象的內(nèi)存示意圖,如圖11所示。
4 結(jié)束語(yǔ)
初學(xué)者往往對(duì)類和對(duì)象的概念理解起來(lái)很不容易,本文通過(guò)類比法對(duì)類和對(duì)象的概念進(jìn)行了分析解釋,并從內(nèi)存層面對(duì)類和對(duì)象進(jìn)行了深入的剖析,讓學(xué)生可以從概念到本質(zhì)更好的理解類和對(duì)象的概念,通過(guò)實(shí)際教學(xué)和對(duì)學(xué)生的調(diào)查表明,通過(guò)此學(xué)習(xí),學(xué)生確實(shí)可以更深一層的理解類和對(duì)象的概念。
參考文獻(xiàn):
[1] 洪陽(yáng). C++中學(xué)習(xí)類的設(shè)計(jì)方法和途徑的探究[J]. 寶鋼科技, 2014,40(1):60-63.
[2] 陳維興, 林小茶. C++面向?qū)ο蟪绦蛟O(shè)計(jì)教程[M].北京: 清華大學(xué)出版社, 2009.
[3] 譚浩強(qiáng). C++程序設(shè)計(jì)[M]. 3版.北京: 清華大學(xué)出版社, 2015.
[4] 本賈尼·斯特勞斯特魯普. C++程序設(shè)計(jì):原理與實(shí)踐(基礎(chǔ)篇)[M]. 2版.北京: 機(jī)械工業(yè)出版社, 2017.