小朋友学C++(1)
Hello World!
在學(xué)C++之前,最好先學(xué)習(xí)一下C語言
讓我們先運(yùn)行一段簡單的代碼,編譯器可以使用 在線C++編譯器 或 Xcode(蘋果系統(tǒng)) 或Dev C++(Windows系統(tǒng))。
運(yùn)行結(jié)果:
Hello World!接下來我們講解一下上面這段程序:
(1)C++ 語言定義了一些頭文件,這些頭文件包含了程序中必需的或有用的信息。上面這段程序中,包含了頭文件 <iostream>。
(2)下一行 using namespace std; 告訴編譯器使用 std 命名空間。命名空間是 C++ 中一個(gè)相對(duì)新的概念。
什么是命名空間呢?
在C++中,名稱(name)可以是符號(hào)常量、變量、宏、函數(shù)、結(jié)構(gòu)、枚舉、類和對(duì)象等等。為了避免,在大規(guī)模程序的設(shè)計(jì)中,以及在程序員使用各種各樣的C++庫時(shí),這些標(biāo)識(shí)符的命名發(fā)生沖突,標(biāo)準(zhǔn)C++引入了關(guān)鍵字namespace(命名空間/名字空間/名稱空間/名域),可以更好地控制標(biāo)識(shí)符的作用域。
做個(gè)比喻,假如三年級(jí)(一)班有個(gè)小朋友叫Teodoro,三年級(jí)(二)班有個(gè)小朋友也叫Teodoro。
在(一)班內(nèi)部說Teodoro時(shí),大家都知道說的是本班的Teodoro。也就是說,(一)班的Teodoro,其作用域是(一)班。
同理,(二)班的Teodoro,其作用域是(二)班。
那如果是校長要找Teodoro呢?因?yàn)橛袃蓚€(gè)叫Teodoro的小朋友,校長需要把班級(jí)名稱都說出來,比如“我找(一)班的Teodoro”,這樣才能明確地指出要找的是哪個(gè)Teodoro。(一)班或(二)班,就叫做命名空間。
(3)下一行 int main() 是主函數(shù),程序從這里開始執(zhí)行。
(4)下一行 cout << "Hello World"; 會(huì)在屏幕上顯示消息 "Hello World"。
(5)下一行 return 0; 終止 main( )函數(shù),并向調(diào)用進(jìn)程返回值 0。
?
面向過程與面向?qū)ο?/h1>
先用C++編寫一個(gè)加法程序
運(yùn)行結(jié)果:
x = 5 y = 10 x + y = 15從上一節(jié)的Hello World程序和本節(jié)的加法程序來看,C和C++貌似看起來差不多,只是修改了一些頭文件和語法而已。那么,二者真的高度相似嗎?
答案是否定的!C和C++差別非常大。
C是面向過程的。
C++既可以面向過程,也可以面向?qū)ο?#xff0c;并且以面向?qū)ο鬄橹鳌?br /> 為何要以面向?qū)ο鬄橹髂?#xff1f;因?yàn)槿糁皇敲嫦蜻^程,用C語言就行了,不用再勞心勞力再創(chuàng)造一種新的語言。C++是一些聰明的程序員在C的基礎(chǔ)上創(chuàng)造、發(fā)展起來的,與C語言最大的區(qū)別就是面向?qū)ο蟆?/p>
C語言的重點(diǎn)在于算法和數(shù)據(jù)結(jié)構(gòu),C程序的設(shè)計(jì)首要考慮的是如何通過一個(gè)過程,對(duì)輸入進(jìn)行運(yùn)算處理得到輸出。
所以c語言是面向過程語言。
而對(duì)于C++,首要考慮的是如何構(gòu)造一個(gè)對(duì)象模型,讓這個(gè)模型能夠契合與之對(duì)應(yīng)的問題域,這樣就可以通過獲取對(duì)象的狀態(tài)信息得到輸出或?qū)崿F(xiàn)過程控制。
從這一點(diǎn)看,C++是面向?qū)ο缶幊?#xff08;OOP)的。
C++還像C語言一樣面向過程。
所以C++既是面向過程的語言 ,也是面向?qū)ο蟮恼Z言。一般來說,用它的面向?qū)ο筮@方面。
以后會(huì)學(xué)到Java。Java不能面向過程,是完全面向?qū)ο蟮摹?/p>
以狗吃屎為例,來說明面向過程和面向過對(duì)象的區(qū)別。
C語言:吃(狗,屎)
這里“吃”是函數(shù)名,“狗”和“屎”是參數(shù)。強(qiáng)調(diào)的是吃這一過程。
C++:狗.吃屎()
這里狗是對(duì)象,吃屎是狗的一個(gè)函數(shù)。語法是一個(gè)完整的主謂賓結(jié)構(gòu)。主語是“狗”,謂語是“吃”,賓語是“屎”。
狗除了吃屎外,還有其他行為,比如汪汪叫,伸舌頭等。語法為
狗.汪汪叫()
狗.伸舌頭()
這一系列行為里,強(qiáng)調(diào)的是“誰來做”,這里是狗來做,所以強(qiáng)調(diào)的是狗這一對(duì)象。
類與對(duì)象
(一)類與對(duì)象
類是由我們根據(jù)客觀事物抽象而成,形成一類事物,然后用類去定義對(duì)象,形成這類事物的具體個(gè)體。
比如小狗是一個(gè)類,你家的“旺財(cái)”則是小狗一個(gè)具體的對(duì)象。
(二)屬性與方法
一般把類的數(shù)據(jù)成員稱為類的屬性,把類的函數(shù)成員稱為方法。
比如小狗這個(gè)類吧,它的屬性有身高、體長、體重、名字、年齡、性別等,它的方法有吃,走,跑,呼吸,吠等。
從這里也可以看出,屬性都是靜態(tài)的,而方法都是動(dòng)作。
(三)程序
運(yùn)行結(jié)果:
running... wang! wang!(四)程序分析
(1)在類定義結(jié)尾處的}后面需要加分號(hào),這是語法要求。否則編程出錯(cuò)。
(2)public表示公有的,在類的外部可以訪問。main()函數(shù)就屬于類的外部。
(3)Dog dog; 這是聲明一個(gè)類型為Dog的對(duì)象dog。也可以寫為
Dog dog1;
Dog mydog;
Dog myDog;
按照慣例,對(duì)象的首字母建議小寫。
(4)dog.name=xxx; 這種賦值的寫法是給對(duì)象設(shè)置屬性。
(5)dog.run(); 這種寫法是調(diào)用對(duì)象的方法。
public, protected, private
面向?qū)ο笥腥筇卣?#xff1a;封裝、繼承、多態(tài)。(具體會(huì)在之后的課程里講)
C++用三個(gè)關(guān)鍵詞來表示訪問范圍:public, protected, private。
public和private作用就是實(shí)現(xiàn)封裝。類外的代碼可以訪問public成員而不能訪問private成員;private成員只能由類成員訪問。
protected的作用則是實(shí)現(xiàn)繼承。protected成員可以被派生類(也叫子類)對(duì)象訪問,不能被用戶代碼類外的代碼訪問。
例1:private修飾屬性和方法
編譯程序,報(bào)錯(cuò):
1.png
這是因?yàn)?#xff0c;name和run()都是私有的,類外的main()沒有權(quán)限訪問dog.name和dog.run()
例2:將private改為protected
編譯程序,報(bào)錯(cuò):
2.png
報(bào)錯(cuò)理由跟上面的差不多,因?yàn)閚ame和run()是protected, 外部的main()沒有權(quán)限訪問。
例3:將protected改為public
程序正常運(yùn)行。運(yùn)行結(jié)果:
running...有些人可能會(huì)想,我不加任何關(guān)鍵字,后果會(huì)怎樣?
例4:不加修飾符
編譯報(bào)錯(cuò),錯(cuò)誤與例1相同:
4.png
可見如果不加任何關(guān)鍵字,無論是屬性還是方法,默認(rèn)都是private。
構(gòu)造函數(shù)
構(gòu)造函數(shù),作用是完成對(duì)象的初始化工作。
可類比于:int a = 1;這里是給變量a賦初值。
構(gòu)造函數(shù)是一種特殊的函數(shù),首先構(gòu)造函數(shù)名與類名是完全一致的,其次構(gòu)造函數(shù)沒有類型。
構(gòu)造函數(shù)可以不帶參數(shù),也可以帶參數(shù)。
運(yùn)行結(jié)果:
Dog’s constructor! Wang Cai is running... Dog’s constructor with name! Xiao Bai is running從運(yùn)行結(jié)果可以看出,構(gòu)造函數(shù)是在生成對(duì)象時(shí)被調(diào)用的,并且不需要顯示調(diào)用。
this指針
this指針是一個(gè)隱含于類中的特殊指針,指向?qū)ο蟊旧怼R簿褪钦f對(duì)象一旦被創(chuàng)建,this指針也就存在了。
就好比你的名字叫做Teodoro,別人說你的時(shí)候用的是Teodoro,但是你說你自己的時(shí)候,用的是“我”。
這個(gè)“我”,在C++和Java中,是用this來表示的。而在Python和Objective-C(蘋果的開發(fā)語言)中,則用self來表示。
程序1
運(yùn)行結(jié)果:
Constructor method with name! Wang Cai is running!分析:
在構(gòu)造函數(shù)里,Name為形參,實(shí)參為main()函數(shù)中的“Wang Cai”。
通過name = Name賦值后,dog的屬性name就有了值“Wang Cai”。
這樣在run()函數(shù)中,就可以打印出屬性name的值出來。
對(duì)程序1稍作改動(dòng),將構(gòu)造函數(shù)的形參改為name,與類的私有屬性name一樣
程序2
運(yùn)行結(jié)果:
Constructor method with name!is running!分析:
類Dog有一個(gè)屬性為name,其作用域?yàn)檎麄€(gè)類,相當(dāng)于這個(gè)類的全局變量。
構(gòu)造函數(shù)的形參為name,其作用域?yàn)闃?gòu)造函數(shù)內(nèi)部,是一個(gè)局部變量。
name = name; 這個(gè)語句發(fā)生在構(gòu)造函數(shù)內(nèi)部,因?yàn)榫植孔兞繒?huì)屏蔽全局變量,兩個(gè)name指的都是形參name。所以這個(gè)語句就相當(dāng)于形參name給自己賦值。這樣類的屬性name沒有被賦值,一直為空。
在執(zhí)行dog.run()時(shí) ,因?yàn)閚ame為空,所以打印出來的就是空值。
如果構(gòu)造函數(shù)的參數(shù)名稱與類的屬性名稱一樣,可以顯示調(diào)用this來加以區(qū)分
程序3
運(yùn)行結(jié)果:
000000000022fe20 000000000022fe30 Constructor method with name! Wang Cai is running! 000000000022fe20分析:
構(gòu)造函數(shù)里的語句為this->name = name; 從打印的內(nèi)存地址就可以看出,this->name與name不是同一回事。
等號(hào)左邊的this->name為對(duì)象的屬性,等號(hào)右邊的name則為構(gòu)造函數(shù)的形參,具體由main()函數(shù)中的實(shí)參“Wang Cai”賦值。
這個(gè)語句的效果為this-> name = name = “Wang Cai”
執(zhí)行run()時(shí),這個(gè)name肯定只能是類的屬性了,而不可能是構(gòu)造函數(shù)的形參。這從打印出來的內(nèi)存地址可以看出來。
實(shí)際上,run()中的name完全等價(jià)于this->name,只是this不用顯示寫出來罷了。當(dāng)然要顯示寫出來也是可以的。
最后,看一個(gè)更簡單的例子。
程序4
運(yùn)行結(jié)果:
Memory address of this: 000000000022fe4f Memory address of a: 000000000022fe4f分析:
從運(yùn)行結(jié)果可以看出,在類外部運(yùn)行的對(duì)象的內(nèi)存地址,與類內(nèi)部運(yùn)行的this的內(nèi)存地址,完全一樣。
這也印證了上面說的,別人口中的Teodoro與Teodoro自己口中的“我”,就是同一個(gè)人。
封裝
面向?qū)ο笥腥齻€(gè)特征:封裝、繼承和多態(tài)。
本節(jié)主要講解封裝。
所有的 C++ 程序都有以下兩個(gè)基本要素:
函數(shù):這是程序中執(zhí)行動(dòng)作的部分,它們被稱為函數(shù)或方法。
數(shù)據(jù):數(shù)據(jù)是程序的信息,會(huì)受到程序函數(shù)的影響,也叫屬性。
封裝是面向?qū)ο缶幊讨械陌褦?shù)據(jù)和操作數(shù)據(jù)的函數(shù)綁定在一起的一個(gè)概念,這樣能避免受到外界的干擾和誤用,從而確保了安全。
我們已經(jīng)知道,類包含私有成員(private)、保護(hù)成員(protected)和公有成員(public)成員。默認(rèn)情況下,所有的數(shù)據(jù)成員和函數(shù)成員都是私有的。
為了使類中的成員變成公有的(即程序中的類外部的其他部分也能訪問),必須在這些成員前使用 public 關(guān)鍵字進(jìn)行聲明。所有定義在 public 標(biāo)識(shí)符后邊的屬性或函數(shù)可以被程序中所有其他的函數(shù)訪問。
例子:
運(yùn)行結(jié)果:
Total is 60上面的類把數(shù)字相加,并返回總和。公有成員 addNum 和 getTotal 是對(duì)外的接口,用戶需要知道它們以便使用類。私有成員 total 是對(duì)外隱藏的(即被封裝起來),用戶不需要了解它,但它又是類能正常工作所必需的。
類的設(shè)計(jì)策略:
通常而言,要把類的數(shù)據(jù)成員設(shè)計(jì)成私有(private),類的函數(shù)成員則根據(jù)實(shí)際需要設(shè)計(jì)成publice, protected或private。
繼承
先編寫程序:
運(yùn)行結(jié)果:
The dog’s weight is 12.5kg The dog has 4 legs breathing... wang! wang!程序分析:
(1)Animal為一個(gè)類,Dog為另一個(gè)類。
class Dog : public Animal 表示Dog類繼承了 Animal類。此時(shí),Animal就成了Dog的基類或父類。Dog就成了Animal的派生類或子類。
(2)體重和呼吸是所有動(dòng)物的共性,所以weight和breathe()定義在類Animal中。腿和吠不是所有動(dòng)物的共性,所以legs和bark()定義在了類Dog中。
(3)class Dog : public Animal , 這里的public表示繼承方式 。
繼承方式有三種:public, protected和private。
① 父類為private的屬性和方法,不能被子類繼承。
② 父類為protected的成員,若被子類public繼承的,仍為子類的protected成員;若被子類protected或private繼承的,變?yōu)樽宇惖膒rivate成員。
③ 父類為public的成員,若被子類public繼承的,仍為子類的public成員;若被子類protected繼承的,變?yōu)樽宇惖膒rotected成員;若被子類private繼承的,變?yōu)樽宇惖膒rivate成員。
注:這些不用強(qiáng)記,編多了自然就知道
(4)根據(jù)(3)中第③條的結(jié)論,若程序改為class Dog : protected Animal,則程序無法通過編譯。因?yàn)閟etWeight()和getWeight()被protected繼承后,變?yōu)镈og的protected成員,而protected成員,無法在類外部(比如main函數(shù)中)訪問。
構(gòu)造函數(shù)的默認(rèn)參數(shù)
?
構(gòu)造函數(shù)可以預(yù)先賦一個(gè)初值,其作用是:在構(gòu)造函數(shù)被調(diào)用時(shí),省略部分或全部參數(shù),這時(shí)就會(huì)使用默認(rèn)參數(shù)代替實(shí)參。
程序:
運(yùn)行結(jié)果:
Constructor method is invoked! Area of rec1 is : 0 Constructor method is invoked! Area of rec2 is : 0 Constructor method is invoked! Area of rec3 is : 50分析:
生成對(duì)象rec1時(shí),沒有傳入拷貝構(gòu)造函數(shù)的實(shí)參,則形參w和h取默認(rèn)值0
w = 0, h = 0
在構(gòu)造函數(shù)中,weight = w = 0, height = h = 0
在area函數(shù)中, weight * height = 0
生成對(duì)象rec2時(shí),傳入實(shí)參5,相當(dāng)于傳入(5,0),則w = 5, h = 0
在構(gòu)造函數(shù)中,weight = w = 5, height = h = 0
在area函數(shù)中,weight * height = 0
生成對(duì)象rec3時(shí),傳入實(shí)參(5,10),則w = 5, h = 10
在構(gòu)造函數(shù)中, weight = w = 5, height = h = 10
在area函數(shù)中,weight * height = 50
子類構(gòu)造函數(shù)調(diào)用父類構(gòu)造函數(shù)
從哲學(xué)層面來看,子類會(huì)繼承父類除private以外的所有成員。
因?yàn)闃?gòu)造函數(shù)是公有的,所以理所當(dāng)然地會(huì)被子類繼承。
程序1:
運(yùn)行結(jié)果:
Shape's constructor method is invoked! Rectangle's constructor method is invoked!分析:
這里構(gòu)造函數(shù)的寫法是
Rectangle() : Shape()
{
子類構(gòu)造函數(shù)本身的語句;
}
這是先調(diào)用父類的構(gòu)造函數(shù),再執(zhí)行它本身的語句。從運(yùn)行結(jié)果也可以看出這一點(diǎn)。
那么,如果不顯示調(diào)用父類的構(gòu)造函數(shù)Shape()呢?父類的構(gòu)造函數(shù)就不被調(diào)用了嗎?
咱們可以用下面的程序來驗(yàn)證。
程序2:
運(yùn)行結(jié)果:
Shape's constructor method is invoked! Rectangle's constructor method is invoked!分析:
從運(yùn)行結(jié)果可以看出,程序1和程序2的運(yùn)行結(jié)果完全一致。也就是說,Shape()即使不顯示調(diào)用,實(shí)際上也會(huì)被調(diào)用。并且調(diào)用順序優(yōu)先于子類本身的構(gòu)造函數(shù)。
“箭頭(->)”和“點(diǎn)號(hào)(.)”操作符的區(qū)別
先看一個(gè)程序:
運(yùn)行結(jié)果:
playing... playing... playing...結(jié)論:
在C++中,
若是普通對(duì)象,使用點(diǎn)號(hào)操作符;
若是指針對(duì)象,有兩種操作方式:
但是(1)不常用,所以(2)中的箭頭操作符用的比較多。
轉(zhuǎn)載于:https://www.cnblogs.com/alan-blog-TsingHua/p/9604147.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的小朋友学C++(1)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 7. 反转整数
- 下一篇: Socket网络编程——C++实现