日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ 面向对象(一)—— 类(Classes)

發(fā)布時(shí)間:2023/12/9 c/c++ 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 面向对象(一)—— 类(Classes) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?類(class)是一種將數(shù)據(jù)和函數(shù)組織在同一個(gè)結(jié)構(gòu)里的邏輯方法。定義類的關(guān)鍵字為class ,其功能與C語言中的struct類似,不同之處是class可以包含函數(shù),而不像struct只能包含數(shù)據(jù)元素。

類定義的形式是:

[cpp]?view plaincopy
  • class?class_name?{??
  • ????permission_label_1:??
  • ????????member1;??
  • ????permission_label_2:??
  • ????????member2;??
  • ????...??
  • }?object_name;??
  • ? ? ? 其中 class_name 是類的名稱 (用戶自定義的類型) ,而可選項(xiàng)object_name 是一個(gè)或幾個(gè)對(duì)象(object)標(biāo)識(shí)。Class的聲明體中包含成員members,成員可以是數(shù)據(jù)或函數(shù)定義,同時(shí)也可以包括允許范圍標(biāo)志 permission labels,范圍標(biāo)志可以是以下三個(gè)關(guān)鍵字中任意一個(gè):private:, public: 或 protected:。它們分別代表以下含義:

    • private :class的private成員,只有同一個(gè)class的其他成員或該class的“friend” class可以訪問這些成員。
    • protected :class的protected成員,只有同一個(gè)class的其他成員,或該class的“friend” class,或該class的子類(derived classes) 可以訪問這些成員。
    • public :class的public成員,任何可以看到這個(gè)class的地方都可以訪問這些成員。

    如果我們?cè)诙x一個(gè)class成員的時(shí)候沒有聲明其允許范圍,這些成員將被默認(rèn)為 private范圍。

    例如:

    [cpp]?view plaincopy
  • class?CRectangle?{??
  • ??
  • ???????????int?x,?y;??
  • ???????public:??
  • ???????????void?set_values?(int,int);??
  • ???????????int?area?(void);??
  • ???}?rect;??
  • ?????
  • ? ? ? 上面例子定義了一個(gè)class CRectangle 和該class類型的對(duì)象變量rect 。這個(gè)class 有4個(gè)成員:兩個(gè)整型變量 (x 和 y) ,在private 部分 (因?yàn)閜rivate 是默認(rèn)的允許范圍);以及兩個(gè)函數(shù), 在 public 部分:set_values() 和 area(),這里只包含了函數(shù)的原型(prototype)。

    ? ? ? 注意:?class名稱與對(duì)象(object)名稱的不同:在上面的例子中,CRectangle 是class 名稱 (即用戶定義的類型名稱),而rect 是一個(gè)CRectangle類型的對(duì)象名稱。它們的區(qū)別就像下面例子中類型名 int和 變量名a 的區(qū)別一樣:

    int a;

    int 是class名稱 (類型名) ,而a 是對(duì)象名 object name (變量)。

    ? ? 在程序中,我們可以通過使用對(duì)象名后面加一點(diǎn)再加成員名稱(同使用C structs一樣),來引用對(duì)象rect 的任何public成員,就像它們只是一般的函數(shù)或變量。例如:

    rect.set_value (3,4);
    myarea = rect.area();

    但我們不能夠引用 x 或 y ,因?yàn)樗鼈兪窃揷lass的 private 成員,它們只能夠在該class的其它成員中被引用。暈了嗎?下面是關(guān)于class CRectangle的一個(gè)復(fù)雜的例子:

    // classes example#include <iostream.h>class CRectangle {int x, y;public:void set_values (int,int);int area (void) {return (x*y);}};void CRectangle::set_values (int a, int b) {x = a;y = b;}int main () {CRectangle rect;rect.set_values (3,4);cout << "area: " << rect.area();} area: 12

    ? ? ?上面代碼中新的東西是在定義函數(shù)set_values().使用的范圍操作符(雙冒號(hào):: )。它是用來在一個(gè)class之外定義該class的成員。注意,我們?cè)贑Rectangle class內(nèi)部已經(jīng)定義了函數(shù)area() 的具體操作,因?yàn)檫@個(gè)函數(shù)非常簡(jiǎn)單。而對(duì)函數(shù)set_values() ,在class內(nèi)部只是定義了它的原型prototype,而其實(shí)現(xiàn)是在class之外定義的。這種在class之外定義其成員的情況必須使用范圍操作符::。

    ? ? ?范圍操作符 (::)?聲明了被定義的成員所屬的class名稱,并賦予被定義成員適當(dāng)?shù)姆秶鷮傩?#xff0c;這些范圍屬性與在class內(nèi)部定義成員的屬性是一樣的。例如,在上面的例子中,我們?cè)诤瘮?shù)set_values() 中引用了private變量x 和 y,這些變量只有在class內(nèi)部和它的成員中才是可見的。

    ? ? 在class內(nèi)部直接定義完整的函數(shù),和只定義函數(shù)的原型而把具體實(shí)現(xiàn)放在class外部的唯一區(qū)別在于,在第一種情況中,編譯器(compiler) 會(huì)自動(dòng)將函數(shù)作為inline 考慮,而在第二種情況下,函數(shù)只是一般的class成員函數(shù)。

    ? ? 我們把 x 和 y 定義為private 成員 (記住,如果沒有特殊聲明,所有class的成員均默認(rèn)為private ),原因是我們已經(jīng)定義了一個(gè)設(shè)置這些變量值的函數(shù) (set_values()) ,這樣一來,在程序的其它地方就沒有辦法直接訪問它們。也許在一個(gè)這樣簡(jiǎn)單的例子中,你無法看到這樣保護(hù)兩個(gè)變量有什么意義,但在比較復(fù)雜的程序中,這是非常重要的,因?yàn)樗沟米兞坎粫?huì)被意外修改 (這里意外指的是從object的角度來講的意外)。

    ? ?使用class的一個(gè)更大的好處是我們可以用它來定義多個(gè)不同對(duì)象(object)。例如,接著上面class CRectangle的例子,除了對(duì)象rect之外,我們還可以定義對(duì)象rectb :

    // class example#include <iostream.h>class CRectangle {int x, y;public:void set_values (int,int);int area (void) {return (x*y);}};void CRectangle::set_values (int a, int b) {x = a;y = b;}int main () {CRectangle rect, rectb;rect.set_values (3,4);rectb.set_values (5,6);cout << "rect area: " << rect.area() << endl;cout << "rectb area: " << rectb.area() << endl;} rect area: 12
    rectb area: 30

    注意: 調(diào)用函數(shù)rect.area() 與調(diào)用rectb.area()所得到的結(jié)果是不一樣的。這是因?yàn)槊恳粋€(gè)class CRectangle 的對(duì)象都擁有它自己的變量 x 和 y,以及它自己的函數(shù)set_value() 和 area()。

    ? ? ? ? 這是基于對(duì)象( object) 和 面向?qū)ο缶幊?(object-oriented programming)的概念的。這個(gè)概念中,數(shù)據(jù)和函數(shù)是對(duì)象(object)的屬性(properties),而不是像以前在結(jié)構(gòu)化編程 (structured programming) 中所認(rèn)為的對(duì)象(object)是函數(shù)參數(shù)。在本節(jié)及后面的小節(jié)中,我們將討論面向?qū)ο缶幊痰暮锰帯?/p>

    在這個(gè)具體的例子中,我們討論的class (object的類型)是CRectangle,有兩個(gè)實(shí)例(instance),或稱對(duì)象(object):rect 和 rectb,每一個(gè)有它自己的成員變量和成員函數(shù)。


    構(gòu)造函數(shù)和析構(gòu)函數(shù) (Constructors and destructors)

    ? ? ? ?對(duì)象(object)在生成過程中通常需要初始化變量或分配動(dòng)態(tài)內(nèi)存,以便我們能夠操作,或防止在執(zhí)行過程中返回意外結(jié)果。例如,在前面的例子中,如果我們?cè)谡{(diào)用函數(shù)set_values( ) 之前就調(diào)用了函數(shù)area(),將會(huì)產(chǎn)生什么樣的結(jié)果呢?可能會(huì)是一個(gè)不確定的值,因?yàn)槌蓡Tx 和 y 還沒有被賦于任何值。

    ? ? ? 為了避免這種情況發(fā)生,一個(gè)class 可以包含一個(gè)特殊的函數(shù):構(gòu)造函數(shù) constructor,它可以通過聲明一個(gè)與class同名的函數(shù)來定義。當(dāng)且僅當(dāng)要生成一個(gè)class的新的實(shí)例 (instance)的時(shí)候,也就是當(dāng)且僅當(dāng)聲明一個(gè)新的對(duì)象,或給該class的一個(gè)對(duì)象分配內(nèi)存的時(shí)候,這個(gè)構(gòu)造函數(shù)將自動(dòng)被調(diào)用。下面,我們將實(shí)現(xiàn)包含一個(gè)構(gòu)造函數(shù)的CRectangle :

    // class example#include <iostream.h>class CRectangle {int width, height;public:CRectangle (int,int);int area (void) {return (width*height);}};CRectangle::CRectangle (int a, int b) {width = a;height = b;}int main () {CRectangle rect (3,4);CRectangle rectb (5,6);cout << "rect area: " << rect.area() << endl;cout << "rectb area: " << rectb.area() << endl;} rect area: 12
    rectb area: 30

    ? ? ? 正如你所看到的,這個(gè)例子的輸出結(jié)果與前面一個(gè)沒有區(qū)別。在這個(gè)例子中,我們只是把函數(shù)set_values換成了class的構(gòu)造函數(shù)constructor。注意這里參數(shù)是如何在class實(shí)例 (instance)生成的時(shí)候傳遞給構(gòu)造函數(shù)的:

    CRectangle rect (3,4);
    CRectangle rectb (5,6);

    ? ? ?同時(shí)你可以看到,構(gòu)造函數(shù)的原型和實(shí)現(xiàn)中都沒有返回值(return value),也沒有void 類型聲明。構(gòu)造函數(shù)必須這樣寫。一個(gè)構(gòu)造函數(shù)永遠(yuǎn)沒有返回值,也不用聲明void,就像我們?cè)谇懊娴睦又锌吹降摹?/p>


    ? ? ??析構(gòu)函數(shù)Destructor?完成相反的功能。它在objects被從內(nèi)存中釋放的時(shí)候被自動(dòng)調(diào)用。釋放可能是因?yàn)樗嬖诘姆秶呀?jīng)結(jié)束了(例如,如果object被定義為一個(gè)函數(shù)內(nèi)的本地(local)對(duì)象變量,而該函數(shù)結(jié)束了);或者是因?yàn)樗且粋€(gè)動(dòng)態(tài)分配的對(duì)象,而被使用操作符delete釋放了。

    ? ? ?析構(gòu)函數(shù)必須與class同名,加水波號(hào)tilde (~) 前綴,必須無返回值

    ? ? ?析構(gòu)函數(shù)特別適用于當(dāng)一個(gè)對(duì)象被動(dòng)態(tài)分別內(nèi)存空間,而在對(duì)象被銷毀的時(shí)我們希望釋放它所占用的空間的時(shí)候。例如:

    // example on constructors and destructors#include <iostream.h>class CRectangle {int *width, *height;public:CRectangle (int,int);~CRectangle ();int area (void) {return (*width * *height);}};CRectangle::CRectangle (int a, int b) {width = new int;height = new int;*width = a;*height = b;}CRectangle::~CRectangle () {delete width;delete height;}int main () {CRectangle rect (3,4), rectb (5,6);cout << "rect area: " << rect.area() << endl;cout << "rectb area: " << rectb.area() << endl;return 0;} rect area: 12
    rectb area: 30



    構(gòu)造函數(shù)重載(Overloading Constructors)

    ? ? ? 像其它函數(shù)一樣,一個(gè)構(gòu)造函數(shù)也可以被多次重載(overload)為同樣名字的函數(shù),但有不同的參數(shù)類型和個(gè)數(shù)。記住,編譯器會(huì)調(diào)用與在調(diào)用時(shí)刻要求的參數(shù)類型和個(gè)數(shù)一樣的那個(gè)函數(shù)(Section 2.3, Functions-II)。在這里則是調(diào)用與類對(duì)象被聲明時(shí)一樣的那個(gè)構(gòu)造函數(shù)。

    ? ? ? 實(shí)際上,當(dāng)我們定義一個(gè)class而沒有明確定義構(gòu)造函數(shù)的時(shí)候,編譯器會(huì)自動(dòng)假設(shè)兩個(gè)重載的構(gòu)造函數(shù) (默認(rèn)構(gòu)造函數(shù)"default constructor" 和復(fù)制構(gòu)造函數(shù)"copy constructor")。例如,對(duì)以下class:

    [cpp]?view plaincopy
  • class?CExample?{??
  • ??public:??
  • ????int?a,b,c;??
  • ????void?multiply?(int?n,?int?m)?{?a=n;?b=m;?c=a*b;?};??
  • };??
  • 沒有定義構(gòu)造函數(shù),編譯器自動(dòng)假設(shè)它有以下constructor 成員函數(shù):

    • Empty constructor

      它是一個(gè)沒有任何參數(shù)的構(gòu)造函數(shù),被定義為nop (沒有語句)。它什么都不做。

      CExample::CExample () { };
    • Copy constructor

      它是一個(gè)只有一個(gè)參數(shù)的構(gòu)造函數(shù),該參數(shù)是這個(gè)class的一個(gè)對(duì)象,這個(gè)函數(shù)的功能是將被傳入的對(duì)象(object)的所有非靜態(tài)(non-static)成員變量的值都復(fù)制給自身這個(gè)object。

      [cpp]?view plaincopy
    • CExample::CExample?(const?CExample&?rv)?{??
    • ?????a=rv.a;??b=rv.b;??c=rv.c;??
    • ?}??
    • ???

    必須注意:這兩個(gè)默認(rèn)構(gòu)造函數(shù)(empty construction 和 copy constructor )只有在沒有其它構(gòu)造函數(shù)被明確定義的情況下才存在。如果任何其它有任意參數(shù)的構(gòu)造函數(shù)被定義了,這兩個(gè)構(gòu)造函數(shù)就都不存在了。在這種情況下,如果你想要有empty construction 和 copy constructor ,就必需要自己定義它們。

    ? ? ? ?當(dāng)然,如果你也可以重載class的構(gòu)造函數(shù),定義有不同的參數(shù)或完全沒有參數(shù)的構(gòu)造函數(shù),見如下例子:

    // overloading class constructors#include <iostream.h>Class CRectangle {int width, height;public:CRectangle ();CRectangle (int,int);int area (void) {return (width*height);}};CRectangle::CRectangle () {width = 5;height = 5;}CRectangle::CRectangle (int a, int b) {width = a;height = b;}int main () {CRectangle rect (3,4);CRectangle rectb;cout << "rect area: " << rect.area() << endl;cout << "rectb area: " << rectb.area() << endl;} rect area: 12
    rectb area: 25

    ? ? ?在上面的例子中,rectb 被聲明的時(shí)候沒有參數(shù),所以它被使用沒有參數(shù)的構(gòu)造函數(shù)進(jìn)行初始化,也就是width 和height 都被賦值為5。

    注意在我們聲明一個(gè)新的object的時(shí)候,如果不想傳入?yún)?shù),則不需要寫括號(hào)():

    CRectangle rectb;?// right
    CRectangle rectb();?// wrong!?



    類的指針(Pointers to classes)

    ? ? ? 類也是可以有指針的,要定義類的指針,我們只需要認(rèn)識(shí)到,類一旦被定義就成為一種有效的數(shù)據(jù)類型,因此只需要用類的名字作為指針的名字就可以了。例如:

    CRectangle * prect;

    ? ? ? 是一個(gè)指向class CRectangle類型的對(duì)象的指針。

    ? ? ? 就像數(shù)據(jù)機(jī)構(gòu)中的情況一樣,要想直接引用一個(gè)由指針指向的對(duì)象(object)中的成員,需要使用操作符 ->。這里是一個(gè)例子,顯示了幾種可能出現(xiàn)的情況:

    // pointer to classes example#include <iostream.h>class CRectangle {int width, height;public:void set_values (int, int);int area (void) {return (width * height);}};void CRectangle::set_values (int a, int b) {width = a;height = b;}int main () {CRectangle a, *b, *c;CRectangle * d = new CRectangle[2];b= new CRectangle;c= &a;a.set_values (1,2);b->set_values (3,4);d->set_values (5,6);d[1].set_values (7,8);cout << "a area: " << a.area() << endl;cout << "*b area: " << b->area() << endl;cout << "*c area: " << c->area() << endl;cout << "d[0] area: " << d[0].area() << endl;cout << "d[1] area: " << d[1].area() << endl;return 0;} a area: 2
    *b area: 12
    *c area: 2
    d[0] area: 30
    d[1] area: 56

    以下是怎樣讀前面例子中出現(xiàn)的一些指針和類操作符 (*, &, ., ->, [ ]):

    • *x 讀作: pointed by x (由x指向的)
    • &x 讀作: address of x(x的地址)
    • x.y 讀作: member y of object x (對(duì)象x的成員y)
    • (*x).y 讀作: member y of object pointed by x(由x指向的對(duì)象的成員y)
    • x->y 讀作: member y of object pointed by x (同上一個(gè)等價(jià))
    • x[0] 讀作: first object pointed by x(由x指向的第一個(gè)對(duì)象)
    • x[1] 讀作: second object pointed by x(由x指向的第二個(gè)對(duì)象)
    • x[n] 讀作: (n+1)th object pointed by x(由x指向的第n+1個(gè)對(duì)象)

    在繼續(xù)向下閱讀之前,一定要確定你明白所有這些的邏輯含義。如果你還有疑問,再讀一遍這一笑節(jié),或者同時(shí)參考 小節(jié) "3.3, 指針(Pointers)" 和 "3.5,?數(shù)據(jù)結(jié)構(gòu)(Structures)".


    由關(guān)鍵字struct和union定義的類

    ? ? ? ? 類不僅可以用關(guān)鍵字class來定義,也可以用struct或union來定義。

    ? ? ? ? 因?yàn)樵贑++中類和數(shù)據(jù)結(jié)構(gòu)的概念太相似了,所以這兩個(gè)關(guān)鍵字struct和class的作用幾乎是一樣的(也就是說在C++中struct定義的類也可以有成員函數(shù),而不僅僅有數(shù)據(jù)成員)。兩者定義的類的唯一區(qū)別在于由class定義的類所有成員的默認(rèn)訪問權(quán)限為private,而struct定義的類所有成員默認(rèn)訪問權(quán)限為public。除此之外,兩個(gè)關(guān)鍵字的作用是相同的。

    ? ? ? ?union的概念與struct和class定義的類不同, 因?yàn)閡nion在同一時(shí)間只能存儲(chǔ)一個(gè)數(shù)據(jù)成員。但是由union定義的類也是可以有成員函數(shù)的。union定義的類訪問權(quán)限默認(rèn)為public。

    總結(jié)

    以上是生活随笔為你收集整理的C++ 面向对象(一)—— 类(Classes)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。