小古銀的官方**(完整教程):
宣告成員變數
基礎講解
宣告定義成員函式
鞏固練習
在之前的教程中我們使用過無數次的類,尤其以字串居多。在我們寫程式的時候,**會越寫越多,這時候為了方便閱讀和重複利用,會從一堆**中找出可以單獨成功能的**,並將這些**封裝成函式;當**量真的很多的時候,**還是不容易理解,這時候還是為了方便理解和重複利用,將一些函式和這些函式需要的共同引數或者全域性變數都打包在一起,封裝成類,這樣就會把整個程式**的複雜度大幅度降低,這就是物件導向出現的理由。類是自定義的資料型別,類裡面的函式叫做成員函式;類裡面的變數叫做成員變數。用類建立的變數叫做物件。
類是為了降低**的複雜度,使**更容易理解和重用而出現的。如果過度封裝則會導致**複雜度大幅度上公升並且後面**越寫越亂而且思維不清晰,最後導致寫**越來越慢而且容易出錯和優化困難。如何合理封裝類,就要靠你平時多學習並且積累經驗,這是乙個經驗活。
物件導向是一種程式設計思想,通過良好的設計讓程式**的邏輯更加清晰,並且可以讓其他程式設計師快速看懂。物件導向的三要素是:封裝、繼承和多型。
之前寫了不少的例子,你應該也發現,成員函式只針對物件有效,某個物件的成員函式是不能操作其他物件的。例如兩個字串變數a
和b
,a.size()
輸出的是a
儲存的字串的字元數量,b.size()
輸出的是b
儲存的字串的字元數量,這兩個size
是不能互相影響的。這也是物件導向思想的一部分。同樣的還有std::pair
,用std::pair
建立的物件都有它們自己各自的成員變數first
和second
。
接下來講的就是如何去設計乙個類。如果乙個類設計得很好,那麼使用類的時候就會非常方便;相反就會非常麻煩。而要設計好乙個類並不簡單,需要努力積累程式設計經驗。
平面座標系中有點(x, y)
,也就是兩個值x
和y
組成乙個點。之前使用了資料型別std::pair
,而現在,我們使用類來宣告定義這樣乙個資料型別point_t
。
// 用於表示二維座標的資料型別
class point_t
;int main(void)
以下**宣告了類point_t
,需要使用關鍵字class
,現在的它沒有成員函式和成員變數。注意類宣告後面是有分號;
的:
class point_t
;
而呼叫就是以下**,用類名宣告物件,換句話說就是,用資料型別宣告變數:
point_t point;
接下來給資料型別新增兩個成員變數x
和y
。
class point_t
;int main(void)
在類中新增乙個成員變數x
和成員變數y
,那麼就可以通過物件來操作它們自身的x
和y
。
需要注意的是:在類中宣告的成員變數,僅僅只是宣告,這個時候是沒有記憶體的。只有當類宣告了物件之後,物件才會被分配到記憶體,而物件的記憶體就是由所有成員變數共同組成的。例如上面**中的point_t point1;
,這個時候point1
才有記憶體,而它的記憶體就是由成員變數x
和y
記憶體的總和,int
型別占用4位元組記憶體,因此point_t
宣告的物件point1
占用8位元組記憶體,而point2
也是占用8位元組記憶體。
另乙個需要注意的是:point1
中的x
和y
是屬於point1
的,point2
中的x
和y
是屬於point2
的,這些x
和y
並不是同乙個變數。類point_t
裡寫的成員變數x
和y
,只是說明它宣告的物件有各自的x
和y
。
現在我們宣告定義乙個成員函式reset()
來設定x
和y
的值。
#include // std::cout std::endl
class point_t
;int main(void)
void point_t::reset(int a, int b)
成員函式的宣告是寫在class
的{}
之間。成員函式的呼叫如下:
point.reset(111, 222);
成員函式的定義可以放在類宣告裡面,但是一般都不會這樣做,宣告和定義一般是分開的。成員函式的定義格式跟普通函式類似,不過成員函式需要在函式名稱前面加上類名,以說明它是這個類的成員函式,如上面**的point_t::
。
類的宣告和定義就說到這裡,其實也並不難。不過你看這個**的時候,肯定發現了乙個問題,我一直強調要初始化,但是這些成員變數沒有初始化。如果你發現了,那就恭喜你,寫**是需要很細心的。這裡的確沒有初始化,因為初始化不能寫在類宣告裡面(除了整數型別的成員變數,但是一般也不會寫在類宣告裡面)。先不要著急,後面會慢慢說明。
在之前教程中簡單講解過std::vector
的使用。std::vector
在**中是非常常用的,我相信你已經非常熟練std::vector
。現在,你可以嘗試一下,設計乙個簡化版的std::vector
。當你完成了這個簡化版的std::vector
,那麼你將會得到以下幾個方面的能力:
接下來就是按照下面指示,完成練習:完成類的宣告。
設計出乙個類,實現乙個儲存int
型別的簡化版的std::vector
,這個類的類名叫做:******_vector
。
這個類含有以下公共的成員函式,以下列出函式名稱和函式功能:
size
:
clear
:
at
:
push_back
:
pop_back
:
insert
:
erase
:
成員函式就有了,現在需要儲存資料,肯定需要使用陣列,這些成員函式基本都是對這個陣列進行操作,因此,這個陣列肯定不能在這些成員函式內宣告,只能宣告為成員變數。這樣就把這個陣列的作用域限制在這個類裡面,而且對這些成員函式而言,就等價於全域性變數,不需要通過引數傳遞。那麼現在就把這個陣列命名為m_array
,但是你需要考慮:陣列應該使用靜態陣列還是動態陣列?
我們還需要乙個變數來儲存這個陣列的元素數量,那麼我們就把它叫做m_size
。
那麼現在你就可以開始動手寫******_vector
的類宣告了。
C 入門教程(七十三) 前置宣告和友元宣告
小古銀的官方 完整教程 友元宣告 include 前置宣告 class b class a class b int main void 類a和類b相互使用對方的指標,由於類b在類a後面,如果沒有前置宣告的話,那麼編譯的時候,編譯器就會報錯,說類a中的型別b沒有定義。中的class b 就是類b的前置...
C 入門教程(十二) 定義函式
小古銀的官方 完整教程 補充知識 既然用過std abs 函式,那麼,現在就以它為例,實現乙個myabs 函式來實現求絕對值。返回值型別 函式名稱 引數型別 引數名稱,引數型別 引數名稱 根據這個格式實現myabs 函式 include int myabs int num else return v...
C 入門教程(12) 定義函式
小古銀的官方 完整教程 既然用過std abs 函式,那麼,現在就以它為例,實現乙個myabs 函式來實現求絕對值。返回值型別 函式名稱 引數型別 引數名稱,引數型別 引數名稱 根據這個格式實現myabs 函式 include int myabs int num else return value ...