c++入门之浅入浅出类——分享给很多想形象理解的人
? ? ? ? 引入類之前,首先引入一個古老的話題:類別,比如int ,char ,double;這些基本的類型方便了我們描述數據(請注意,這句話很重要),類型的存在就是為了方便我們描述數據的。而c++中的類其實作用也是:方便我們描述數據。因此,我們可以這么認為:引入類的作用,就是為了讓我們可以像使用int 這些類型一樣,來描述我們想要表達的數據。盡管很多時候我們需要把我們想描述的數據抽象化。因此,我們有理由將類和int,char這些基本類型一視同仁(這個思想是很重要的!!!,但要在編程的時候認識到這點并不容易)。而實質上,引入類的初衷:就是讓我們能夠像使用基本類型使用我們定義的類,并能夠像基本類型那樣操作自如。
? ? ? ? 再看一個基本的話題:比如定義了一個變量 ,比如int x;很不幸的是,我們已經養成了習慣,習慣把x叫作“變量”,同樣的把int叫作類型,這對我們認識和使用類造成了很大的不便。在類中,也會定義類變量,但我們把它叫對象。比如,我們定義貓科動物為一類:class Cat{};通常類型名大寫,請注意,這里的Cat是我們定義的類,或者說是類型。即Cat和int,char等并無差異性。比如我們可以通過這個Cat類型,定義一些貓科動物。比如Cat cat(就是定義了貓),Cat tiger(定義了老虎)。我們發現:貓和老虎都是貓科動物(就像1和2都是整數一樣)。這里的cat,tiger,我們稱之為對象。其實想叫作變量也可以,但還是跟著叫對象吧。
? ? ? ? 接下來,通過一段代碼初步認識類:
?
1 # ifndef STOCK00_H 2 #define STOCK00_H 3 # include "string" 4 class Stock 5 { 6 private: 7 std::string company; 8 long shares; 9 double share_val; 10 double total_val; 11 void set_tot()//思考這個函數定義的意義何在 12 { 13 total_val = shares*share_val; 14 } 15 public: 16 Stock::Stock(); 17 void acquire(const std::string &co, long n, double pr); 18 void buy(long num, double price); 19 void sell(long num, double price); 20 void updata(double price); 21 void show(); 22 }; 23 #endif //ifbdef...endif成對出現?
這段代碼定義了一個名叫Stock的類。首先,我們在這個代碼中看到的是:public和private,中文意思公共和私有(這種描述和其功能很吻合)。共有的意思是對外公開的,客戶可以對其訪問的。我們也把這個叫做接口。私有的意思是用戶對其不可直接訪問的。上面代碼可以看到:我們在private中定義了很多基本類型變量。我們把這些基本類型變量叫做數據成員。而public中定義的是函數成員,我們也叫做方法。當然不一定非要把數據成員都放在private中,而把函數成員都放在public中,取決于你想讓用戶訪問什么。關于這方面,請具體參考c++ prime,并通過自己的實戰體會。
在此,僅僅總結這么個東西(很重要):我們定義了一個類,比如貓科動物。我們首先想到的肯定是:既然是貓科動物,首先肯定要有一些描述它的信息:比如體重啊,毛色啊,名字啊(假如有),甚至眼睛大小啊等等。而這些其實本質上,就是我們說的數據成員,即我們需要定義一些基本類型變量來描述我們的類具有哪些特征。但是現在,我們是面向對象編程:我們需要封裝。假如現在有一個用戶手上有一只具有這些特征的值的貓,他想根據這些數據知道這個貓幾歲了???。這便引入了這樣一個問題:我們類的存在不只是為了存儲一只貓的各類類型的值。(那樣的話我們直接用結構體就好了,為何要使用類呢???),我們是想根據這些值能 做些什么比較方便的事,而這些事最終被反饋到用戶。那么成員函數的存在就是:利用這些基本類型變量,完成某項工作。但用戶并不需要知道怎么完成,我只需要知道貓有幾歲???知道貓有幾歲這個工作毫無疑問是通過函數完成的,或者說我們用什么方法(函數)來知道貓有幾歲(過度很自然)。比如有一個函數indicate_age()可以幫我們做這件事,則用戶可以通過調用類——貓中的indicate_age()方法來實現這個愿望。這一點也表明了,這個indicate_age()方法要放在public,這樣用戶才有訪問使用它的權限。(假如用戶不想讓人知道名字,可以放在private中)
(如果清閑,可以思考Python中定義類有何異同)
請注意,上面那段代碼中public中只是聲明了函數原型,但是并沒定義這些函數,當然我們可以在public中直接定義,但沒必要,顯得很啰嗦。下面給出這些函數的定義:
1 # include "iostream" 2 # include "stock00.h" 3 4 void Stock::acquire(const std::string &co, long n, double pr) 5 { 6 company = co; 7 if (n < 0) 8 { 9 std::cout << "Number of shares can't be negative;" 10 << company << "shares set to 0.\n"; 11 shares = 0; 12 } 13 else 14 shares = n; 15 share_val = pr; 16 set_tot(); 17 } 18 19 void Stock::buy(long num, double price) 20 { 21 if (num < 0) 22 { 23 std::cout << "Number of shares can't be negative." 24 << "Transaction is aborted.\n"; 25 } 26 else 27 { 28 shares += num; 29 share_val = price; 30 set_tot(); 31 } 32 } 33 34 void Stock::sell(long num, double price) 35 { 36 using std::cout; 37 if (num < 0) 38 { 39 cout << "Number of shares can't be negative." 40 << "Transaction is aborted.\n"; 41 } 42 else if (num>shares) 43 { 44 cout << "You can't sell more than you have!" 45 << "Transaction is aborted.\n"; 46 } 47 else 48 { 49 shares -= num; 50 share_val = price; 51 set_tot(); 52 } 53 } 54 55 void Stock::updata(double price) 56 { 57 share_val = price; 58 set_tot(); 59 } 60 61 void Stock::show() 62 { 63 std::cout << "Company:" << company 64 << "Shares:" << shares << "\n" 65 << "Shares Price:$" << share_val 66 << "Total worth:$" << total_val << std::endl; 67 } 68 69 Stock::Stock() 70 { 71 company = "no name"; 72 shares = 0; 73 share_val = 0.0; 74 }我們重新用一個文件來定義這些函數:具體的細節不再贅述,想描述的是每個函數的抬頭,都采用了Stock::,這其實是表明這些函數的作用域是類作用域,比如我們外面也聲明了acquire()函數,那么兩者是可以區分的。這個類作用域十分重要,具體的可以參考c++ prime,
在這里,我們發現,給出的第一個代碼中,有這樣一個函數:Stock::Stock(),這個函數對類的數據成員進行了賦值(實際上就是初始化)。這個函數有兩個特點:1 沒有返回類型;2 名字和類的名字要一致。我們把這種函數叫構造函數。實際編寫代碼中,我們有時候沒有寫構造函數,但是貌似并不是報錯,但這并不意味著構造函數是非必須的。實際上,構造函數是必須的。我們在創建類 對象的時候(就是定義類 變量的時候)將先自動調用構造函數(即由系統自動調用),然后才能生成我們的類 對象。也就是構造函數是用來被創建對象的,從而構造函數是不能通過對象去調用的。這一是十分重要的。關于構造函數耳朵顯示,和隱式初始化可以參考c++ primer。
上面完成了對一個類的定義。下面給出調用它的代碼:
1 # include"iostream" 2 # include"stock00.h" 3 int main() 4 { 5 Stock fluffy_the_car; 6 fluffy_the_car.acquire("NanoSmart", 20, 12.50); 7 fluffy_the_car.show(); 8 fluffy_the_car.buy(15, 18.125); 9 fluffy_the_car.show(); 10 fluffy_the_car.sell(400, 20.00); 11 fluffy_the_car.show(); 12 fluffy_the_car.buy(300000, 40.125); 13 fluffy_the_car.show(); 14 system("pause"); 15 //int i; 16 //std::cout << "i is:" << i << std::endl;//c++中未初始化造成報錯,不同于C語言. 17 return 0; 18 }上面的代碼是多么的簡潔,假如我們是客戶,我們只需要知道類方法怎么使用即可,即怎么調用接口,就能知道我們的貓有幾歲。站在用戶的角度講,這段程序很簡單!!!而這,就是類產生的目的!!!
? ? ? ? C++中類的誕生是一種很重要的思想,而所有關于C++類相關的,最重要的思想在于:能夠讓我們像使用其他類一樣方便的使用我們定義的自己數據類型。認識到這一點的重要性在于:當我們思想中認識到我們自己創建的類和int,char并無區別的時候,就意味著,int,char ,double這些基本類型所有的操作,定義的類對象也應該有:比如,初始化,賦值,甚至比較大小。具有指針,具有數據(類數組),可以將類作為函數的返回值和參數。所以,我們思考類的角度,應該從數據和結構的角度去思考!
關于類:還想說明兩點很重要的地方:
1? 聲明類只是創建了對象的形式,而非創建對象本身。因此,在創建對象之前,我們所定義的東西,是不被分配內存空間的,比如當我們聲明int類型的時候,只有定義了 int i,i才有內存空間
2? 關于類的作用域。在很多地方,都討論過作用域。作用域到底意味著什么???作用域意味著變量的生存周期,意味著作用域與作用域之間的獨立性。而類的作用域,一個最明顯的特征是,當我們定義類方法的時候,采用的是:classname ::funcname? 這樣的限定方式,這樣即使兩種方法使用了同一個名字,但由于處于不同的類作用域中,兩者的同時存在并不沖突!
?
轉載于:https://www.cnblogs.com/shaonianpi/p/9853246.html
總結
以上是生活随笔為你收集整理的c++入门之浅入浅出类——分享给很多想形象理解的人的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CF858F Wizard's Tour
- 下一篇: 拓展编辑器(五)_监听事件