C++類 &對象詳解
一 定義 C++ 對象
類提供了對象的藍圖,所以基本上,對象是根據(jù)類來創(chuàng)建的。聲明類的對象,就像聲明基本類型的變量一樣。下面的語句聲明了類 Box 的兩個對象:
Box?Box1;??????????//?聲明?Box1,類型為?Box Box?Box2;??????????//?聲明?Box2,類型為?Box
對象 Box1 和 Box2 都有它們各自的數(shù)據(jù)成員。
二 訪問數(shù)據(jù)成員
類的對象的公共數(shù)據(jù)成員可以使用直接成員訪問運算符 (.) 來訪問。為了更好地理解這些概念,讓我們嘗試一下下面的實例:
#includeusing?namespace?std; class?Box { ???public: ??????double?length;???//?長度 ??????double?breadth;??//?寬度 ??????double?height;???//?高度 }; int?main(?) { ???Box?Box1;????????//?聲明?Box1,類型為?Box ???Box?Box2;????????//?聲明?Box2,類型為?Box ???double?volume?=?0.0;?????//?用于存儲體積 ? ???//?box?1?詳述 ???Box1.height?=?5.0;? ???Box1.length?=?6.0;? ???Box1.breadth?=?7.0; ???//?box?2?詳述 ???Box2.height?=?10.0; ???Box2.length?=?12.0; ???Box2.breadth?=?13.0; ???//?box?1?的體積 ???volume?=?Box1.height?*?Box1.length?*?Box1.breadth; ???cout?<<?"Box1?的體積:"?<<?volume?<<endl; ???//?box?2?的體積 ???volume?=?Box2.height?*?Box2.length?*?Box2.breadth; ???cout?<<?"Box2?的體積:"?<<?volume?<<endl; ???return?0; }
當上面的代碼被編譯和執(zhí)行時,它會產(chǎn)生下列結(jié)果:
Box1?的體積:210 Box2?的體積:1560
三?定義?C++?對象訪問數(shù)據(jù)成員
需要注意的是,私有的成員和受保護的成員不能使用直接成員訪問運算符 (.) 來直接訪問。我們將在后續(xù)的教程中學習如何訪問私有成員和受保護的成員。
四 類 & 對象詳解
到目前為止,我們已經(jīng)對 C++ 的類和對象有了基本的了解。下面的列表中還列出了其他一些 C++ 類和對象相關(guān)的概念,可以點擊相應(yīng)的鏈接進行學習。
類成員函數(shù) 類的成員函數(shù)是指那些把定義和原型寫在類定義內(nèi)部的函數(shù),就像類定義中的其他變量一樣。 類訪問修飾符 類成員可以被定義為 public、private 或 protected。默認情況下是定義為 private。 構(gòu)造函數(shù) & 析構(gòu)函數(shù) 類的構(gòu)造函數(shù)是一種特殊的函數(shù),在創(chuàng)建一個新的對象時調(diào)用。類的析構(gòu)函數(shù)也是一種特殊的函數(shù),在刪除所創(chuàng)建的對象時調(diào)用。 C++ 拷貝構(gòu)造函數(shù) 拷貝構(gòu)造函數(shù),是一種特殊的構(gòu)造函數(shù),它在創(chuàng)建對象時,是使用同一類中之前創(chuàng)建的對象來初始化新創(chuàng)建的對象。 C++ 友元函數(shù) 友元函數(shù)可以訪問類的 private 和 protected 成員。 C++ 內(nèi)聯(lián)函數(shù) 通過內(nèi)聯(lián)函數(shù),編譯器試圖在調(diào)用函數(shù)的地方擴展函數(shù)體中的代碼。 C++ 中的 this 指針 每個對象都有一個特殊的指針this,它指向?qū)ο蟊旧怼? C++ 中指向類的指針 指向類的指針方式如同指向結(jié)構(gòu)的指針。實際上,類可以看成是一個帶有函數(shù)的結(jié)構(gòu)。 C++ 類的靜態(tài)成員 類的數(shù)據(jù)成員和函數(shù)成員都可以被聲明為靜態(tài)的。 1、類成員函數(shù)
類的成員函數(shù)是指那些把定義和原型寫在類定義內(nèi)部的函數(shù),就像類定義中的其他變量一樣。類成員函數(shù)是類的一個成員,它可以操作類的任意對象,可以訪問對象中的所有成員。
讓我們看看之前定義的類 Box,現(xiàn)在我們要使用成員函數(shù)來訪問類的成員,而不是直接訪問這些類的成員:
class?Box { ???public: ??????double?length;?????????//?長度 ??????double?breadth;????????//?寬度 ??????double?height;?????????//?高度 ??????double?getVolume(void);//?返回體積 };
成員函數(shù)可以定義在類定義內(nèi)部,或者單獨使用范圍解析運算符 ::來定義。在類定義中定義的成員函數(shù)把函數(shù)聲明為內(nèi)聯(lián)的,即便沒有使用 inline 標識符。所以您可以按照如下方式定義Volume()函數(shù):
class?Box { ???public: ??????double?length;??????//?長度 ??????double?breadth;?????//?寬度 ??????double?height;??????//?高度 ??? ??????double?getVolume(void) ??????{ ?????????return?length?*?breadth?*?height; ??????} };
您也可以在類的外部使用范圍解析運算符 ::定義該函數(shù),如下所示:
double?Box::getVolume(void) { ????return?length?*?breadth?*?height; }
在這里,需要強調(diào)一點,在 :: 運算符之前必須使用類名。調(diào)用成員函數(shù)是在對象上使用點運算符(.),這樣它就能操作與該對象相關(guān)的數(shù)據(jù),如下所示:
Box?myBox;??????????//?創(chuàng)建一個對象 myBox.getVolume();??//?調(diào)用該對象的成員函數(shù)
讓我們使用上面提到的概念來設(shè)置和獲取類中不同的成員的值:
#includeusing?namespace?std; class?Box { ???public: ??????double?length;?????????//?長度 ??????double?breadth;????????//?寬度 ??????double?height;?????????//?高度 ??????//?成員函數(shù)聲明 ??????double?getVolume(void); ??????void?setLength(?double?len?); ??????void?setBreadth(?double?bre?); ??????void?setHeight(?double?hei?); }; //?成員函數(shù)定義 double?Box::getVolume(void) { ????return?length?*?breadth?*?height; } void?Box::setLength(?double?len?) { ????length?=?len; } void?Box::setBreadth(?double?bre?) { ????breadth?=?bre; } void?Box::setHeight(?double?hei?) { ????height?=?hei; } //?程序的主函數(shù) int?main(?) { ???Box?Box1;????????????????//?聲明?Box1,類型為?Box ???Box?Box2;????????????????//?聲明?Box2,類型為?Box ???double?volume?=?0.0;?????//?用于存儲體積 ? ???//?box?1?詳述 ???Box1.setLength(6.0);? ???Box1.setBreadth(7.0);? ???Box1.setHeight(5.0); ???//?box?2?詳述 ???Box2.setLength(12.0);? ???Box2.setBreadth(13.0);? ???Box2.setHeight(10.0); ???//?box?1?的體積 ???volume?=?Box1.getVolume(); ???cout?<<?"Box1?的體積:"?<<?volume?<<endl; ???//?box?2?的體積 ???volume?=?Box2.getVolume(); ???cout?<<?"Box2?的體積:"?<<?volume?<<endl; ???return?0; }
當上面的代碼被編譯和執(zhí)行時,它會產(chǎn)生下列結(jié)果:
Box1?的體積:?210 Box2?的體積:?1560
2、類訪問修飾符
數(shù)據(jù)隱藏是面向?qū)ο缶幊痰囊粋€重要特點,它防止函數(shù)直接訪問類類型的內(nèi)部成員。類成員的訪問限制是通過在類主體內(nèi)部對各個區(qū)域標記public、private、protected來指定的。關(guān)鍵字 public、private、protected 稱為訪問說明符。
一個類可以有多個 public、protected 或 private 標記區(qū)域。每個標記區(qū)域在下一個標記區(qū)域開始之前或者在遇到類主體結(jié)束右括號之前都是有效的。成員和類的默認訪問修飾符是 private。
class?Base?{ ? ???public: ? ??//?public?members?go?here ? ???protected: ? ??//?protected?members?go?here ? ???private: ? ??//?private?members?go?here ? };
公有(public)成員
公有成員在程序中類的外部是可訪問的。您可以不使用任何成員函數(shù)來設(shè)置和獲取公有變量的值,如下所示:
#includeusing?namespace?std; ? class?Line { ???public: ??????double?length; ??????void?setLength(?double?len?); ??????double?getLength(?void?); }; ? //?成員函數(shù)定義 double?Line::getLength(void) { ????return?length?; } ? void?Line::setLength(?double?len?) { ????length?=?len; } ? //?程序的主函數(shù) int?main(?) { ???Line?line; ? ???//?設(shè)置長度 ???line.setLength(6.0);? ???cout?<<?"Length?of?line?:?"?<<?line.getLength()?<<endl; ? ???//?不使用成員函數(shù)設(shè)置長度 ???line.length?=?10.0;?//?OK:?因為?length?是公有的 ???cout?<<?"Length?of?line?:?"?<<?line.length?<<endl; ???return?0; }
當上面的代碼被編譯和執(zhí)行時,它會產(chǎn)生下列結(jié)果:
Length?of?line?:?6 Length?of?line?:?10
私有(private)成員
私有成員變量或函數(shù)在類的外部是不可訪問的,甚至是不可查看的。只有類和友元函數(shù)可以訪問私有成員。
默認情況下,類的所有成員都是私有的。例如在下面的類中,width是一個私有成員,這意味著,如果您沒有使用任何訪問修飾符,類的成員將被假定為私有成員:
class?Box { ???double?width; ???public: ??????double?length; ??????void?setWidth(?double?wid?); ??????double?getWidth(?void?); };
實際操作中,我們一般會在私有區(qū)域定義數(shù)據(jù),在公有區(qū)域定義相關(guān)的函數(shù),以便在類的外部也可以調(diào)用這些函數(shù),如下所示:
#includeusing?namespace?std; ? class?Box { ???public: ??????double?length; ??????void?setWidth(?double?wid?); ??????double?getWidth(?void?); ? ???private: ??????double?width; }; ? //?成員函數(shù)定義 double?Box::getWidth(void) { ????return?width?; } ? void?Box::setWidth(?double?wid?) { ????width?=?wid; } ? //?程序的主函數(shù) int?main(?) { ???Box?box; ? ???//?不使用成員函數(shù)設(shè)置長度 ???box.length?=?10.0;?//?OK:?因為?length?是公有的 ???cout?<<?"Length?of?box?:?"?<<?box.length?<<endl; ? ???//?不使用成員函數(shù)設(shè)置寬度 ???//?box.width?=?10.0;?//?Error:?因為?width?是私有的 ???box.setWidth(10.0);??//?使用成員函數(shù)設(shè)置寬度 ???cout?<<?"Width?of?box?:?"?<<?box.getWidth()?<<endl; ? ???return?0; }
當上面的代碼被編譯和執(zhí)行時,它會產(chǎn)生下列結(jié)果:
Length?of?box?:?10 Width?of?box?:?10
保護(protected)成員
保護成員變量或函數(shù)與私有成員十分相似,但有一點不同,保護成員在派生類(即子類)中是可訪問的。
在下一個章節(jié)中,您將學習到派生類和繼承的知識。現(xiàn)在您可以看到下面的實例中,我們從父類Box派生了一個子類smallBox。
下面的實例與前面的實例類似,在這里width成員可被派生類 smallBox 的任何成員函數(shù)訪問。
#includeusing?namespace?std; ? class?Box { ???protected: ??????double?width; }; ? class?SmallBox:Box?//?SmallBox?是派生類 { ???public: ??????void?setSmallWidth(?double?wid?); ??????double?getSmallWidth(?void?); }; ? //?子類的成員函數(shù) double?SmallBox::getSmallWidth(void) { ????return?width?; } ? void?SmallBox::setSmallWidth(?double?wid?) { ????width?=?wid; } ? //?程序的主函數(shù) int?main(?) { ???SmallBox?box; ? ???//?使用成員函數(shù)設(shè)置寬度 ???box.setSmallWidth(5.0); ???cout?<<?"Width?of?box?:?"<<?box.getSmallWidth()?<<?endl; ? ???return?0; }
當上面的代碼被編譯和執(zhí)行時,它會產(chǎn)生下列結(jié)果:
Width?of?box?:?5
3、類構(gòu)造函數(shù) & 析構(gòu)函數(shù) 類的構(gòu)造函數(shù)
類的構(gòu)造函數(shù)是類的一種特殊的成員函數(shù),它會在每次創(chuàng)建類的新對象時執(zhí)行。
構(gòu)造函數(shù)的名稱與類的名稱是完全相同的,并且不會返回任何類型,也不會返回 void。構(gòu)造函數(shù)可用于為某些成員變量設(shè)置初始值。
下面的實例有助于更好地理解構(gòu)造函數(shù)的概念:
#includeusing?namespace?std; ? class?Line { ???public: ??????void?setLength(?double?len?); ??????double?getLength(?void?); ??????Line();??//?這是構(gòu)造函數(shù) ? ???private: ??????double?length; }; ? //?成員函數(shù)定義,包括構(gòu)造函數(shù) Line::Line(void) { ????cout?<<?"Object?is?being?created"?<<?endl; } ? void?Line::setLength(?double?len?) { ????length?=?len; } ? double?Line::getLength(?void?) { ????return?length; } //?程序的主函數(shù) int?main(?) { ???Line?line; ? ???//?設(shè)置長度 ???line.setLength(6.0);? ???cout?<<?"Length?of?line?:?"?<<?line.getLength()?<<endl; ? ???return?0; }
當上面的代碼被編譯和執(zhí)行時,它會產(chǎn)生下列結(jié)果:
Object?is?being?created Length?of?line?:?6
帶參數(shù)的構(gòu)造函數(shù)
默認的構(gòu)造函數(shù)沒有任何參數(shù),但如果需要,構(gòu)造函數(shù)也可以帶有參數(shù)。這樣在創(chuàng)建對象時就會給對象賦初始值,如下面的例子所示:
#includeusing?namespace?std; ? class?Line { ???public: ??????void?setLength(?double?len?); ??????double?getLength(?void?); ??????Line(double?len);??//?這是構(gòu)造函數(shù) ? ???private: ??????double?length; }; ? //?成員函數(shù)定義,包括構(gòu)造函數(shù) Line::Line(?double?len) { ????cout?<<?"Object?is?being?created,?length?=?"?<<?len?<<?endl; ????length?=?len; } ? void?Line::setLength(?double?len?) { ????length?=?len; } ? double?Line::getLength(?void?) { ????return?length; } //?程序的主函數(shù) int?main(?) { ???Line?line(10.0); ? ???//?獲取默認設(shè)置的長度 ???cout?<<?"Length?of?line?:?"?<<?line.getLength()?<<endl; ???//?再次設(shè)置長度 ???line.setLength(6.0);? ???cout?<<?"Length?of?line?:?"?<<?line.getLength()?<<endl; ? ???return?0; }
當上面的代碼被編譯和執(zhí)行時,它會產(chǎn)生下列結(jié)果:
Object?is?being?created,?length?=?10 Length?of?line?:?10 Length?of?line?:?6
使用初始化列表來初始化字段
使用初始化列表來初始化字段:
Line::Line(?double?len):?length(len) { ????cout?<<?"Object?is?being?created,?length?=?"?<<?len?<<?endl; }
上面的語法等同于如下語法:
Line::Line(?double?len) { ????cout?<<?"Object?is?being?created,?length?=?"?<<?len?<<?endl; ????length?=?len; }
假設(shè)有一個類 C,具有多個字段 X、Y、Z 等需要進行初始化,同理地,您可以使用上面的語法,只需要在不同的字段使用逗號進行分隔,如下所示:
C::C(?double?a,?double?b,?double?c):?X(a),?Y(b),?Z(c) { ??.... }
類的析構(gòu)函數(shù)
類的析構(gòu)函數(shù)是類的一種特殊的成員函數(shù),它會在每次刪除所創(chuàng)建的對象時執(zhí)行。
析構(gòu)函數(shù)的名稱與類的名稱是完全相同的,只是在前面加了個波浪號(~)作為前綴,它不會返回任何值,也不能帶有任何參數(shù)。析構(gòu)函數(shù)有助于在跳出程序(比如關(guān)閉文件、釋放內(nèi)存等)前釋放資源。
下面的實例有助于更好地理解析構(gòu)函數(shù)的概念:
#includeusing?namespace?std; ? class?Line { ???public: ??????void?setLength(?double?len?); ??????double?getLength(?void?); ??????Line();???//?這是構(gòu)造函數(shù)聲明 ??????~Line();??//?這是析構(gòu)函數(shù)聲明 ? ???private: ??????double?length; }; ? //?成員函數(shù)定義,包括構(gòu)造函數(shù) Line::Line(void) { ????cout?<<?"Object?is?being?created"?<<?endl; } Line::~Line(void) { ????cout?<<?"Object?is?being?deleted"?<<?endl; } ? void?Line::setLength(?double?len?) { ????length?=?len; } ? double?Line::getLength(?void?) { ????return?length; } //?程序的主函數(shù) int?main(?) { ???Line?line; ? ???//?設(shè)置長度 ???line.setLength(6.0);? ???cout?<<?"Length?of?line?:?"?<<?line.getLength()?<<endl; ? ???return?0; }
當上面的代碼被編譯和執(zhí)行時,它會產(chǎn)生下列結(jié)果:
Object?is?being?created Length?of?line?:?6 Object?is?being?deleted
拷貝構(gòu)造函數(shù)
拷貝構(gòu)造函數(shù)是一種特殊的構(gòu)造函數(shù),它在創(chuàng)建對象時,是使用同一類中之前創(chuàng)建的對象來初始化新創(chuàng)建的對象。拷貝構(gòu)造函數(shù)通常用于:
通過使用另一個同類型的對象來初始化新創(chuàng)建的對象。
復(fù)制對象把它作為參數(shù)傳遞給函數(shù)。
復(fù)制對象,并從函數(shù)返回這個對象。
如果在類中沒有定義拷貝構(gòu)造函數(shù),編譯器會自行定義一個。如果類帶有指針變量,并有動態(tài)內(nèi)存分配,則它必須有一個拷貝構(gòu)造函數(shù)。拷貝構(gòu)造函數(shù)的最常見形式如下:
classname?(const?classna
概念 | 描述 |
---|