C基礎講義筆記(干貨)_第1頁
C基礎講義筆記(干貨)_第2頁
C基礎講義筆記(干貨)_第3頁
C基礎講義筆記(干貨)_第4頁
C基礎講義筆記(干貨)_第5頁
已閱讀5頁,還剩221頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

傳智播客C++課程講義1、C++對C的擴展1簡單的C++程序1.1求圓的周長和面積數據描述:半徑,周長,面積均用實型數表示數據處理:輸入半徑r;計算周長=2*n*r;計算面積=心戶:輸出半徑,周長,面積;方法1:用結構化方法編程,求圓的周長和面積//countthegirthandareaofcircle#include<iostream.h>usingnamestd;voidmain(){doubler,girth,area;constdoublePI=3.1415;cout?"Pleaseinputradius:\n";〃操作符重載cin?r;〃輸入girth=2*PI*r;

area=PI*r*cout?"radius="?r?endl;cout?"girth="?girth?endl;cout?"area="?area?endl;方法2:用面向對象方法編程,求圓的周長和面積分析“圓”是抽象的類類型半徑?建立具體的圓(對象)圓的周長?面積?實例化分析圓類成員變量半徑成員函數置半徑值求圓的半徑求周長求面積#include<iostream.h>usingnamestd;classCircle{doubleradius;〃成員變量public:〃類的訪問控制voidSet_Radius(doubler){radius=r;}〃成員函數doubleGet_Radius(){returnradius;}〃通過成員函數設置成員變量doubleGet_Girth() {return2*3.14f*radius;}〃通過成員函數獲取成員變量doubleGet_Area() {return3.14f*radius*radius;}};voidmain()(CircleA,B;〃用類定義對象A.Set_Radius(6.23);〃類的調用cout?"A.Radius="?A.Get_Radius()?endl;cout?"A.Girth="?A.Get_Girth()?endl;cout?"A.Area="?A.Get_Area()?endl;B.Set_Radius(10.5);cout?"B.radius="?B.Get_Radius()?endl;cout?"B.Girth="?B.Get_Girth()?endl;cout?"B.Area="?B.Get_Area()?endl;)總結:建立類、對象、成員變量、成員函數,輸入輸入流基本概念。1.2初學者易犯錯誤模型//demo02_circle_err.cpp#include<iostream>usingnamespacestd;〃c++的命名空間classcircle(public:doubler;doublepi=3.1415926;doublearea=pi*r*r;intmain()(circlepi;cout?"請輸入area"?endl;cin?pi.r;cout?pi.area?endl;〃舌L碼system("pause");return0;總結:從內存四區(qū)的角度,解釋為什么會出現(xiàn)亂碼理解為什么需要成員函數2程序設計方法的發(fā)展歷程面向過程的結構化程序設計方法?設計思路-自頂向下、逐步求精。采用模塊分解與功能抽象,自頂向下、分而治之。?程序結構:按功能劃分為若干個基本模塊,形成一個樹狀結構。各模塊間的關系盡可能簡單,功能上相對獨立:每一模塊內部均是由順序、選擇和循環(huán)三種基本結構組成。其模塊化實現(xiàn)的具體方法是使用子程序。?優(yōu)點:有效地將一個較復雜的程序系統(tǒng)設計任務分解成許多易于控制和處理的子任務,便于開發(fā)和維護。?缺點:可重用性差、數據安全性差、難以開發(fā)大型軟件和圖形界面的應用軟件把數據和處理數據的過程分離為相互獨立的實體。當數據結構改變時,所有相關的處理過程都要進行相應的修改。每一種相對于老問題的新方法都要帶來額外的開銷。圖形用戶界面的應用程序,很難用過程來描述和實現(xiàn),開發(fā)和維護也都很困難。面向對象的方法將數據及對數據的操作方法封裝在一起,作為一個相互依存、不可分離的整體一一對象。對同類型對象抽象出其共性,形成類。類通過一個簡單的外部接口,與外界發(fā)生關系。對象與對象之間通過消息進行通信。面向對象的基本概念對象一般意義上的對象:是現(xiàn)實世界中一個實際存在的事物。可以是有形的(比如一輛汽車),也可以是無形的(比如一項計劃)。是構成世界的一個獨立單位,具有?靜態(tài)特征:可以用某種數據來描述?動態(tài)特征:對象所表現(xiàn)的行為或具有的功能?面向對象方法中的對象:是系統(tǒng)中用來描述客觀事物的一個實體,它是用來構成系統(tǒng)的一個基本單位。對象由一組屬性和一組行為構成。屬性:用來描述對象靜態(tài)特征的數據項。行為:用來描述對象動態(tài)特征的操作序列。類?分類一一人類通常的思維方法?分類所依據的原則一一抽象-忽略事物的非本質特征,只注意那些與當前目標有關的本質特征,從而找出事物的共性,把具有共同性質的事物劃分為一類,得出一個抽象的概念。-例如,石頭、樹木、汽車、房屋等都是人們在長期的生產和生活實踐中抽象出的概念。?面向對象方法中的"類"具有相同屬性和服務的一組對象的集合為屬于該類的全部對象提供了抽象的描述,包括屬性和行為兩個主要部分。類與對象的關系:猶如模具與鑄件之間的關系,一個屬于某類的對象稱為該類的一個實例。封裝也就是把客觀事物封裝成抽象的類,并且類可以把自己的數據和方法只讓可信的類或者對象操作,對不可信的進行信息隱藏。把對象的屬性和服務結合成一個獨立的系統(tǒng)單元。盡可能隱蔽對象的內部細節(jié)。對外形成一個邊界(或者說一道屏障),只保留有限的對外接口使之與外部發(fā)生聯(lián)系。繼承對于軟件復用有著重要意義,是面向對象技術能夠提高軟件開發(fā)效率的重要原因之一。定義:特殊類的對象擁有其一般類的全部屬性與服務,稱作特殊類對一般類的繼承。例如:將輪船作為一個一般類,客輪便是一個特殊類。多態(tài)多態(tài)是指在一般類中定義的屬性或行為,被特殊類繼承之后,可以具有不同的數據類型或表現(xiàn)出不同的行為。這使得同一個屬性或行為在一般類及其各個特殊類中具有不同的語義。面向對象的軟件工程面向對象的軟件工程是面向對象方法在軟件工程領域的全面應用。它包括:面向對象的分析(00A)面向對象的設計(00D)面向對象的編程(OOP)面向對象的測試(。。丁)面向對象的軟件維護(OOSM)總結:面向過程程序設計:數據結構+算法主要解決科學計算問題,用戶需求簡單而固定特點:分析解決問題所需要的步驟利用函數實現(xiàn)各個步驟依次調用函數解決問題問題:軟件可重用性差軟件可維護性差構建的軟件無法滿足用戶需求面向對象程序設計:由現(xiàn)實世界建立軟件模型將現(xiàn)實世界中的事物直接映射到程序中,可直接滿足用戶需求特點:直接分析用戶需求中涉及的各個實體在代碼中描述現(xiàn)實世界中的實體在代碼中關聯(lián)各個實體協(xié)同工作解決問題優(yōu)勢:構建的軟件能夠適應用戶需求的不斷變化直接利用面向過程方法的優(yōu)勢而避開其劣勢3C語言和C++語言關系c語言是在實踐的過程中逐步完善起來的沒有深思熟慮的設計過程使用時存在很多“灰色地帶”殘留量過多低級語言的特征直接利用指針進行內存操作C語言的目標是高效最終程序執(zhí)行效率的高效當面向過程方法論暴露越來越多的缺陷的時候,業(yè)界開始考慮在工程項目中引入面向對象的設計方法,而第一個需要解決的問題就是:高效的面向對象語言,并且能夠兼容已經存在的代碼。C語言+面向對象方法論===》ObjectiveC/C++C語言和C++并不是對立的競爭關系C++是C語言的加強,是一種更好的C語言C++是以C語言為基礎的,并且完全兼容C語言的特性學習C++并不會影響原有的C語言知識,相反會根據加深對C的認知;學習C++可以接觸到更多的軟件設計方法,并帶來更多的機會。C++是一種更強大的C,通過學習C++能夠掌握更多的軟件設計方法C++是Java/C#/D等現(xiàn)代開發(fā)語言的基礎,學習C++后能夠快速掌握這些語言C++是各大知名軟件企業(yè)挑選人才的標準之一C++對C的加強namespace命名空間C++命名空間基本常識所謂namespace,是指標識符的各種可見范圍。C++標準程序庫中的所有標識符都被定義于一個名為std的namespace中。一:<iostream>和<iostream.h>格式不一樣,前者沒有后綴,實際上,在你的編譯器include文件夾里面可以看到,二者是兩個文件,打開文件就會發(fā)現(xiàn),里面的代碼是不一樣的。后綴為.h的頭文件C++標準已經明確提出不支持了,早些的實現(xiàn)將標準庫功能定義在全局空間里,聲明在帶.h后綴的頭文件里,C++標準為了和C區(qū)別開,也為了正確使用命名空間,規(guī)定頭文件不使用后綴.h。因此,1)當使用<iostream.h>時,相當于在c中調用庫函數,使用的是全局命名空間,也就是早期的C++實現(xiàn);2)當使用<iostream>的時候,該頭文件沒仃定義全局命名空間,必須使用namespacestd;這樣才能正確使用couto二: 由于namespace的概念,使用C++標準程序庫的任何標識符時,可以有三種選擇:1、直接指定標識符。例如std::ostream而不是ostream。完整語句如下:std::cout<<std::hex?3.4?std::endl;2、使用using關鍵字。usingstd::cout;usingstd::endl;usingstd::cin;以上程序可以寫成cout?std::hex?3.4?endl;3、最方便的就是使用usingnamespacestd;例如:usingnamespacestd;這樣命名空間std內定義的所有標識符都有效(曝光)。就好像它們被聲明為全局變量一樣。那么以上語句可以如下寫:cout?hex?3.4?endl;因為標準庫非常的龐大,所以程序員在選擇的類的名稱或函數名時就很有可能和標準庫中的某個名字相同。所以為了避免這種情況所造成的名字沖突,就把標準庫中的一切都被放在名字空間std中。但這又會帶來了一個新問題。無數原有的C++代碼都依賴于使用了多年的偽標準庫中的功能,他們都是在全局空間下的。所以就有了<iostream.h>和<iostream>等等這樣的頭文件,一個是為了兼容以前的C++代碼,一個是為了支持新的標準。命名空間std封裝的是標準程序庫的名稱,標準程序庫為了和以前的頭文件區(qū)別,一般不加“.h”C++命名空間定義及使用語法在C++中,名稱(name)可以是符號常量、變量、宏、函數、結構、枚舉、類和對象等等。為了避免,在大規(guī)模程序的設計中,以及在程序員使用各種各樣的C++庫時,這些標識符的命名發(fā)生沖突,標準C++引入了關鍵字namespace(命名空間/名字空間/名稱空間/名域),可以更好地控制標識符的作用域。*/std是C++標準命名空間,C++標準程序庫中的所有標識符都被定義在std中,比如標準庫中的類iostream>vector等都定義在該命名空間中,使用時要加上using聲明(usingnamespacestd)或using指示(如std::string>std::vector<int>).*/

C中的命名空間在C語言中只有一個全局作用域C語言中所有的全局標識符共享同一個作用域標識符之間可能發(fā)生沖突C++中提出了命名空間的概念命名空間將全局作用域分成不同的部分不同命名空間中的標識符可以同名而不會發(fā)生沖突命名空間可以相互嵌套全局作用域也叫默認命名空間*//*C++命名空間的定義:namespacename{...}*/C++命名空間的使用:使用整個命名空間:usingnamespacename;使用命名空間中的變量:usingname::variable;默認情況下可以直接使用默認命名空間中的所有標識符使用默認命名空間中的變量:::variable默認情況下可以直接使用默認命名空間中的所有標識符73C++命名空間編程實踐namespaceNameSpaceA(inta=0;}namespaceNameSpaceB(inta=1;namespaceNameSpaceC(structTeacher(charname[10];intage;):)}intmain()(usingnamespaceNameSpaceA;usingNameSpaceB::NameSpaceC::Teacher;printf(z,a=%d\n〃,a);printf(^a=%d\n〃,NameSpaceB::a);NameSpaceB::NameSpaceC::Teachert2Teachertl={"aaa”,3};printf(z,=%s\n”,11.name);printfC/tl.age=%d\n”,tl.age);system("pause");return0;4結論1)當使用<iostream》的時候,該頭文件沒有定義全局命名空間,必須使用namespacestd;這樣才能正確使用cout。若不引入usingnamespacestd ,需要這樣做。std::coutoC++標準為了和C區(qū)別開,也為了正確使用命名空間,規(guī)定頭文件不使用后綴.h。C++命名空間的定義:namespacename{...}usingnamespaceNameSpaceA;namespce定義可嵌套?!皩嵱眯浴痹黾?include"iostream"usingnamespacestd;〃(:語言中的變量都必須在作用域開始的位置定義?。 –++中更強調語言的“實用性”,所有的變量都可以在需要使用時再定義。intmainll()(inti=0;printf("ddd");intk;system("pause");return0;register關鍵字增強“register關鍵字請求編譯器讓變量a直接放在寄存器里面,速度快〃在c語言中register修飾的變量不能取地址,但是在C++里面做了內容/*//Iregister關鍵字的變化register關鍵字請求“編譯器”將局部變量存儲于寄存器中C語言中無法取得register變量地址在C++中依然支持register關鍵字C++編譯器有自己的優(yōu)化方式,不使用register也可能做優(yōu)化C++中可以取得register變量的地址//2C++編譯器發(fā)現(xiàn)程序中需要取register變量的地址時,register對變量的聲明變得無效。//3早期C語言編譯器不會對代碼進行優(yōu)化,因此register變量是一個很好的補充。*/intmain22()(registerinta=0;printf("&a=%x\nH,&a);system("pause");return0;其他補充:請閱讀《register關鍵字常識課外閱讀.docx》4.4變量檢測增強在c語言中,重復定義多個同名的全局變量是合法的在C++中,不允許定義多個同名的全局變量C語言中多個同名的全局變量最終會被鏈接到全局數據區(qū)的同一個地址空間上intg_var;intg_var=1;C++直接拒絕這種二義性的做法。7intmain(intargc,char*argv[])(printf("g_var=%d\n",g_var);return0;)struct類型加強struct類型的加強:C語言的struct定義了一組變量的集合,C編譯器并不認為這是一種新的類型C++中的struct是一個新類型的定義聲明structStudent(charname[100];intage;};intmain(intargc,char*argv[]){Studentsi={"wang",1};Students2={”wang2",2};return0;}C++中所有的變量和函數都必須有類型/*C++中所有的變量和函數都必須有類型C語言中的默認類型在C++中是不合法的函數f的返回值是什么類型,參數又是什么類型?函數g可以接受多少個參數?*/〃更換成.cpp試試他)printf("i=%d\n"/i);g()(return5;}intmain(intargc,char*argv[])(f(10);printf("g()=%d\n",g(l,2,3,4,5));getchar();return0;}總結:/*在c語言中intf();表示返回值為int,接受任意參數的函數intf(void);表示返回值為int的無參函數在C++中intf();和屁小。16具有相同的意義,都表示返回值為int的無參函數*/C++更加強調類型,任意的程序元素都必須顯示指明類型4.2-4.6屬于語法級別的增強。4.7新增Bool類型關鍵字C++中的布爾類型C++在C語言的基本類型系統(tǒng)之上增加了boolC++中的bool可取的值只有true和false理論上bool只占用一個字節(jié),如果多個bool變量定義在一起,可能會各占一個bit,這取決于編譯器的實現(xiàn)true代表真值,編譯器內部用1來表示false代表非真值,編譯器內部用0來表示bool類型只有true(非0)和false(0)兩個值C++編譯器會在賦值時將非0值轉換為true,0值轉換為falseintmain(intargc,char*argv[])(inta;

boolb=true;printf("b=%d,sizeof(b)=%d\n"/b,sizeof(b));b=4;a=b;printf("a=%d,b=%d\n”,a,b);b=-4;a=b;printf("a=%d,b=%d\n"/a,b);a=10;b=a;printf("a=%d,b=%d\n"/a,b);b=0;printf("b=%d\n",b);system("pausen);return0;}4.8三目運算符功能增強1三目運算符在C和C++編譯器的表現(xiàn)intmain()(inta=10;intb=20;〃返回一個最小數并且給最小數賦值成3〃三目運算符是一個表達式,表達式不可能做左值(a<b?a:b)=30;printf("a=%d,b=%d\n",azb);system("pausen);return0;}2結論1)c語言返回變量的值C++語言是返回變量本身C語言中的三目運算符返回的是變量值,不能作為左值使用C++中的三目運算符可直接返回變量本身,因此可以出現(xiàn)在程序的任何地方2)注意:三目運算符可能返回的值中如果有一個是常量值,則不能作為左值使用(a<b?1:b)=30;3)C語言如何支持類似C++的特性呢?====>當左值的條件:要有內存空間;C++編譯器幫助程序員取了一個地址而已思考:如何讓C中的三目運算法當左值呢?5C/C++中的constconst基礎知識(用法、含義、好處)intmain()(constinta;intconstb;constint*c;int*constd;constint*conste;return0;|Intfuncl(const)初級理解:const是定義常量==》const意味著只讀含義:〃第一個第二個意思一樣代表一個常整形數〃第三個c是一個指向常整形數的指針(所指向的內存數據不能被修改,但是本身可以修改)〃第四個d常指針(指針變量不能被修改,但是它所指向內存空間可以被修改)〃第五個e一個指向常整形的常指針(指針和它所指向的內存空間,均不能被修改)Const好處〃合理的利用const,〃1指針做函數參數,可以有效的提高代碼可讀性,減少bug;//2清楚的分清參數的輸入和輸出特性intsetTeacher_err(constTeacher*p)Const修改形參的時候,在利用形參不能修改指針所向的內存空間2C中“冒牌貨”intmain()(constinta=10;int*p=(int*)&a;printf(,,a===>%d\n"/a);*p=ll;printf("a===>%d\nH/a);printf(nHello \n");return0;解釋:C++編譯器對const常量的處理當碰見常量聲明時,在符號表中放入常量問題:那有如何解釋取地址編譯過程中若發(fā)現(xiàn)使用常量則直接以符號表中的值替換編譯過程中若發(fā)現(xiàn)對const使用了extern或者&操作符,則給對應的常量分配存儲空間(兼容C)?聯(lián)想:int&a=l(err)&constint&a=10(ok)?C++中const符號表原理圖C++編譯器雖然可能為const常量分配空間,但不會使用其存儲空間中的值。結論:C語言中的const變量C語言中const變量是只讀變量,有自己的存儲空間C++中的const常量可能分配存儲空間,也可能不分配存儲空間當const常量為全局,并且需要在其它文件中使用當使用&操作符取const常量的地址3const和#define相同之處〃練習解釋為什么//#defineN10intmain(){constinta=1;constintb=2;intarray[a+b]={0};inti=0;for(i=0;i<(a+b);i++){printf("array[%d]=%d\n",i,array。]);}getchar();return0;|C++中的const修飾的,是一個真正的常量,而不是C中變量(只讀)。在const修飾的常量編譯期間,就已經確定下來了。4const和#define的區(qū)別對比加深C++中的const常量類似于宏定義constintc=5;弋#definec5C++中的const常量與宏定義不同const常量是由編譯器處理的,提供類型檢查和作用域檢查宏定義由預處理器處理,單純的文本替換〃在funcl定義a,在func2中能使用嗎?〃在funcl中定義的b,在func2中能使用嗎?練習voidfunl()(#definea10constintb=20;//#undefa#undef}voidfun2(){printf("a=%d\n",a);//printf("b=%d\n"/b);}intmain(){funl();fun2();return0;5結論C語言中的const變量C語言中const變量是只讀變量,有自己的存儲空間C++中的const常量可能分配存儲空間,也可能不分配存儲空間當const常量為全局,并且需要在其它文件中使用,會分配存儲空間當使用&操作符,取const常量的地址時,會分配存儲空間當constint&a=10;const修飾引用時,也會分配存儲空間6引用專題講座1引用(普通引用)變量名回顧變量名實質上是一段連續(xù)存儲空間的別名,是一個標號(門牌號)程序中通過變量來申請并命名內存空間通過變量的名字可以使用存儲空間問題1:對一段連續(xù)的內存空間只能取一個別名嗎?1引用概念a)在C++中新增加了引用的概念b)引用可以看作一個已定義變量的別名c)引用的語法:Type&name=var;d)引用做函數參數那?(引用作為函數參數聲明時不進行初始化)voidmain01()(inta=10;〃c編譯器分配4個字節(jié)內存。。。a內存空間的別名int&b=a;〃b就是a的別名。。。a=11;〃直接賦值{int*p=&a;*p=12;printf("a%d\n”,a);)b=14;printf("a:%db:%d"za,b);system("pauseH);2引用是C++的概念屬于C++編譯器對c的擴展問題:C中可以編譯通過嗎?intmain()(inta=0;int&b=a;//int*constb=&ab=11;//*b=11;return0;結論:請不要用C的語法考慮b=ll3引用做函數參數普通引用在聲明時必須用其它的變量進行初始化,引用作為函數參數聲明時不進行初始化〃05復雜數據類型的引用structTeacher{charname[64];intage;);voidprintfT(Teacher*pT)(cout?pT->age?endl;|〃pT是tl的別名,相當于修改了tlvoidprintfT2(Teacher&pT)(//cout?pT.age?endl;pT.age=33;}〃pT和tl的是兩個不同的變量voidprintfT3(TeacherpT)(cout?pT.age?endl;pT.age=45;〃只會修改pT變量,不會修改tl變量}voidmain()(Teachertl;tl.age=35;printfT(&tl);printfT2(tl);〃pT是tl的別名printf("tl.age:%d\n",tl.age);//33printfT3(tl);//pT是形參ztlcopy一份數據給pT //—>pT=tlprintf(Htl.age:%d\n",tl.age);//35cout?"hello..."?endl;system(Hpause");return;4引用的意義1)引用作為其它變量的別名而存在,因此在一些場合可以代替指針2)引用相對于指針來說具有更好的可讀性和實用性Bintswapl(int&a,int&b)(intt=a;a=b;b=t;return0;)5引用本質思考思考1:C++編譯器背后做了什么工作?intmainO(inta=10;int&b=a;〃b是a的別名,請問C++編譯器后面做了什么工作?b=11;cout<<b=t;return0;)bb=t;return0;)printf(*a:%d\n*,a);printf(*b:%d\n*,b);printf(*&a:%d\n*,&a);printfC&b:%d\n*,&b);〃請思考:對同一內存空間可以取好幾個名字嗎?system(*pause*);return0;單獨定義的引用時,必須初始化;說明很像一個常量思考2:普通引用有自己的空間嗎?structTeacer{int&a;int&b;);intmain()(printf(*sizeof(Teacher)%d\n*,sizeof(Teacer));system("pause");return0;)引用是一個有地址,引用是常量。。。。。char*constp6引用的本質1)引用在C++中的內部實現(xiàn)是一個常指針2)C++編譯器在編譯過程中使用常指針作為引用的內部實現(xiàn),因此引用所占用的空間大小與指針相同。3)從使用的角度,引用會讓人誤會其只是一個別名,沒有自己的存儲空間。這是C++為了實用性而做出的細節(jié)隱藏void func(int&a) void func(int*consta){ _ {a=5; *a=5} )Intmain()(intx=10;func(x);)4)請仔細對比間接賦值成立的三個條件1定義兩個變量(一個實參一個形參)2建立關聯(lián)實參取地址傳給形參3*p形參去間接的修改實參的值7引用結論1)引用在實現(xiàn)上,只不過是把:間接賦值成立的三個條件的后兩步和二為一〃當實參傳給形參引用的時候,只不過是C++編譯器幫我們程序員手工取了一個實參地址,傳給了形參引用(常量指針)2)當我們使用引用語法的時,我們不去關心編譯器引用是怎么做的當我們分析奇怪的語法現(xiàn)象的時,我們才去考慮C++編譯器是怎么做的8函數返回值是引用(引用當左值)C++引用使用時的難點:當函數返回值為引用時若返回棧變量不能成為其它引用的初始值不能作為左值使用若返回靜態(tài)變量或全局變量可以成為其他引用的初始值即可作為右值使用,也可作為左值使用C++鏈式編程中,經常用到引用,運算符重載專題返回值是基礎類型,當引用intgetAAl()(inta;a=10;returna;}〃基礎類型a返回的時候,也會有一個副本int&getAA2(){inta;a=10;returna;int*getAA3()inta;a=10;return&a;}返回值是static變量,當引用“static修飾變量的時候,變量是一個狀態(tài)變量intj(){staticinta=10;a++;printf(Ha:%d\n",a);returna;|int&jl()(staticinta=10;a++;printf("a:%d\n",a);returna;int*j2(){staticinta=10;a++;printf("a:%d\n”,a);return&a;voidmain22()(〃j()的運算結果是一個數值,沒有內存地址,不能當左值。。。。。//II=100;//*(a>b?&a:&b)=111;〃當被調用的函數當左值的時候,必須返回一個引用。。。。。jl()=100;〃編譯器幫我們打造了環(huán)境jl{);*(j2())=200;〃相當于我們程序員手工的打造做左值的條件j2();system("pause");返回值是形參,當引用intgl(int*p){*p=100;return*p;}int&g2(int*p)//(*p=100;return*p;〃當我們使用引用語法的時候,我們不去關心編譯器引用是怎么做的〃當我們分析亂碼這種現(xiàn)象的時候,我們才去考慮C++編譯器是怎么做的。。。。voidmain23()(intal=10;al=g2(&al);int&a2=g2(&al);〃用引用去接受函數的返回值,是不是亂碼,關鍵是看返回的內存空間是不是被編譯器回收了。。。。pnntf("al:%d\n",al);printf("a2:%d\n",a2);system(Hpause");返回值非基礎類型structTeachar(charname[64];intage;};〃如果返回引用不是基礎類型,是一個類,那么情況非常賦值。。涉及到copy構造函數和二操作重載,拋成。。。。structTeachar(charname[64];intage;};〃如果返回引用不是基礎類型,是一個類,那么情況非常賦值。。涉及到copy構造函數和=操作重載,拋磚。。。。structTeachar&OpTeacher(structTeachar&tl)9指針引用#include"iostream"usingnamespacestd;structTeacher(charname[64];intage;};intgetTe(Teacher**myp){Teacher+p=(Teacher*)malloc(sizeof(Teacher));if(p==NULL){return-1;)memset(pz0,sizeof(Teacher));p->age=33;myp=p;//return0;}〃指針的引用而已intgetTe2(Teacher*&myp)(myp=(Teacher*)malloc(sizeof(Teacher));myp->age=34;return0;)voidmain333(){Teacher*p=NULL;//getTe(&p);getTe2(p);printf("age:%d\n",p->age);system("pauseH);)2常引用下面開始進入const引用難點

1使用變量初始化const引用思考costint&a=bPKconstint&a=10;????問題:const引用,在C++中可以聲明const引用constType&name=var;const引用讓變量擁有只讀屬性案例1:intmain()(inta=10;constint&b=a;//int*p=(int*)&b;b=11;//err//*P=11;〃只能用指針來改變了cout<<*b >*?a<<endl;printf(*a:%d\n*,a);printfC*b:%d\n*,b);printf("&a:%d\n”,&a);printf(*&b:%d\n*?&b);return0;system(*pause*)return0;)案例2:voidmain41()(inta=10;constint&b=a;〃const引用使用變量a初始化a=11;//b=12;〃通過引用修改a,對不起修改不了system("pause");structTeacherl(charname[64];intage;};voidprintTe2(constTeacherl*constpt)(}voidprintTe(constTeacherl&t)(//t.age=11;}voidmain42()(Teacherltl;tl.age=33;printTe(tl);system(*pause*);}2使用字面量常量初始化const引用思考:1、用變量對const引用初始化,const引用分配內存空間了嗎?2、用常量對const引用初始化,const引用分配內存空間了嗎?voidmain()(constintb=10;printf&b);//int&al=19;如果不加const編譯失敗constint&a=19;printfC&a:%d\n”,&a);system(*pause*);}■3綜合案例voidmain()(〃普通引用inta=10;int&b=a;〃常量引用:讓變量引用只讀屬性constint&c=a;〃常量引用初始化分為兩種//I用變量初始化常量引用{intx=20;constint&y=x;printf(Hy:%d\n"zy);}//2用常量初始化常量引用〃int&m=10;〃引用是內存空間的別名字面量10沒有內存空間沒有方法做引用constint&m=10;}cout?"hello..."?endl;system("pauseM);return;}3const引用結論1)Const&inte相當于constint*conste2)普通引用相當于int*constel3)當使用常量(字面量)對const引用進行初始化時,C++編譯器會為常量值分配空間,并將引用名作為這段空間的別名4)使用字面量對const引用初始化后,將生成一個只讀變量4const修飾類后續(xù)課程介紹5綜合練習int&j()staticinta=0;returna;int&g()(inta=0;returna;)intmain()(inta=g();int&b=g();j()=10;printf("a=%d\n"/a);printf("b=%d\n"/b);printf("f()=%d\n",f());system("pause");return0;}7C++對C的函數擴展1inline內聯(lián)函數C++中的const常量可以替代宏常數定義,如:constintA=3;0#defineA3C++中是否有解決方案替代宏代碼片段呢?(替代宏代碼片段就可以避免宏的副作用!)C++中推薦使用內聯(lián)函數替代宏代碼片段C++中使用inline關鍵字聲明內聯(lián)函數內聯(lián)函數聲明時inline關鍵字必須和函數定義結合在一起,否則編譯器會直接忽略內聯(lián)請求?!ê晏鎿Q和函數調用區(qū)別#include"iostream"usingnamespacestd;#defineMYFUNC(a,b)((a)<(b)?(a):(b))inlineintmyfunc(inta,intb)(returna<b?a:b;}intmain()(inta=1;intb=3;//intc=myfunc(++a,b);〃頭疼系統(tǒng)intc=MYFUNC(++azb);printf("a=%d\n",a);printf("b=%d\n"/b);printf(Hc=%d\n',/c);system("pause");return0;}說明1:必須inlineintmyfuncfinta,intb)和函數體的實現(xiàn),寫在一塊說明2C++編譯器可以將一個函數進行內聯(lián)編譯被C++編譯器內聯(lián)編譯的函數叫做內聯(lián)函數內聯(lián)函數在最終生成的代碼中是沒有定義的C++編譯器直接將函數體插入在函數調用的地方內聯(lián)函數沒有普通函數調用時的額外開銷(壓棧,跳轉,返回)說明3:C++編譯器不一定準許函數的內聯(lián)請求!說明4內聯(lián)函數是一種特殊的函數,具有普通函數的特征(參數檢查,返回類型等)內聯(lián)函數是對編譯器的一種請求,因此編譯器可能拒絕這種請求內聯(lián)函數由編譯器處理,直接將編譯后的函數體插入調用的地方宏代碼片段由預處理器處理,進行簡單的文本替換,沒有任何編譯過程說明5:現(xiàn)代C++編譯器能夠進行編譯優(yōu)化,因此一些函數即使沒有inline聲明,也可能被編譯器內聯(lián)編譯另外,一些現(xiàn)代C++編譯器提供了擴展語法,能夠對函數進行強制內聯(lián)如:g++中的_attribute_((always_inline))屬性說明6:C++中內聯(lián)編譯的限制:不能存在任何形式的循環(huán)語句不能存在過多的條件判斷語句函數體不能過于龐大不能對函數進行取址操作函數內聯(lián)聲明必須在調用語句之前編譯器對于內聯(lián)函數的限制并不是絕對的,內聯(lián)函數相對于普通函數的優(yōu)勢只是省去了函數調用時壓棧,跳轉和返回的開銷。因此,當函數體的執(zhí)行開銷遠大于壓棧,跳轉和返回所用的開銷時,那么內聯(lián)將無意義。結論:1)內聯(lián)函數在編譯時直接將函數體插入函數調用的地方2)inline只是一種請求,編譯器不一定允許這種請求3)內聯(lián)函數省去了普通函數調用時壓棧,跳轉和返回的開銷2默認參數/*1C++中可以在函數聲明時為參數提供一個默認值,當函數調用時沒有指定這個參數的值,編譯器會自動用默認值代替VvoidmyPrint(intx=3)(printf(*x:%d*,x);)/*2函數默認參數的規(guī)則只有參數列表后面部分的參數才可以提供默認參數值一旦在一個函數調用中開始使用默認參數值,那么這個參數后的所有參數都必須使用默認參數值*/〃默認參數voidprintAB(intx=3)(printf("x:%d\n",x);}〃在默認參數規(guī)則,如果默認參數出現(xiàn),那么右邊的都必須有默認參數voidprintABC(inta,intb,intx=3,inty=4zintz=5)(printf(”x:%d\n”,x);}intmain62(intargc,char*argv[]){printAB(2);printAB();system("pause");return0;}3函數占位參數函數占位參數占位參數只有參數類型聲明,而沒有參數名聲明一般情況下,在函數體內部無法使用占位參數*/intfunc(inta,intb,int){returna+b;}intmain01(){//func(lz2);〃可以嗎?printfC'funcfl,2,3)=%d\n"/func(lz2,3));getchar();return0;)4默認參數和占位參數可以將占位參數與默認參數結合起來使用意義為以后程序的擴展留下線索兼容C語言程序中可能出現(xiàn)的不規(guī)范寫法*/〃C++可以聲明占位符參數,占位符參數一般用于程序擴展和對C代碼的兼容intfunc2(inta,intb,int=0)(returna+b;}voidmain()(〃如果默認參數和占位參數在一起,都能調用起來func2(l,2);func2(l,2,3);system("pause");結論:〃如果默認參數和占位參數在一起,都能調用起來5函數重載(Overroad)函數重載概念1函數重載概念函數重載(FunctionOverload)用同一個函數名定義不同的函數當函數名和不同的參數搭配時函數的含義不同2函數重載的判斷標準/*函數重載至少滿足下面的一個條件:參數個數不同參數類型不同參數順序不同*/3函數返回值不是函數重載的判斷標準實驗1:調用情況分析;實驗2:判斷標準〃兩個難點:重載函數和默認函數參數混搭重載函數和函數指針/*intfunc(intx)(returnx;}intfunc(inta,intb){returna+b;}intfunc(constchar*s){returnstrlen(s);}intmain()(intc=0;c=func(l);printf("c=%d\n"zc);c=func(lz2);printf("c=%d\n",c);c=func("12345");printf("c=%d\n",c);printf("Pressentertocontinuegetchar();return0;}*/函數重載的調用準則編譯器調用重載函數的準則將所有同名函數作為候選者嘗試尋找可行的候選函數精確匹配實參通過默認參數能夠匹配實參通過默認類型轉換匹配實參匹配失敗最終尋找到的可行候選函數不唯一,則出現(xiàn)二義性,編譯失敗。無法匹配所有候選者,函數未定義,編譯失敗。函數重載的注意事項重載函數在本質上是相互獨立的不同函數(靜態(tài)鏈編)重載函數的函數類型是不同的函數返回值不能作為函數重載的依據函數重載是由函數名和參數列表決定的。函數重載是發(fā)生在一個類中里面函數重載遇上函數默認參數〃當函數默認參數遇上函數重載會發(fā)生什么intfunc(inta,intb,intc=0)(returna*b*c;}intfunc(inta,intb)(returna+b;}〃1個參數的允許嗎intfuncfinta)(returna+b;intmain(){intc=0;c=func(l,2);〃存在二義性,調用失敗,編譯不能通過printf("c=%d\n”,c);printf("Pressentertocontinuegetchar();return0;}*/函數重載和函數指針結合函數重載與函數指針當使用重載函數名對函數指針進行賦值時根據重載規(guī)則挑選與函數指針參數列表一致的候選者嚴格匹配候選者的函數類型與函數指針的函數類型*//*intfunc(intx)//int(inta)(returnx;}intfunc(inta,intb)returna+b;}intfunc(constchar*s)(returnstrlen(s);}typedefint(*PFUNC)(inta);//int(inta)intmain()(intc=0;PFUNCp=func;c=P(l);printf("c=%d\n"zc);printf("Pressentertocontinuegetchar();return0;*/函數重載、重寫、重定義后續(xù)課程。8附錄附錄1:C++語言對C語言擴充和增強的幾點具體體現(xiàn)在C語言塊注釋的形式/*Explana.tioxiSexiterice*/的基礎上,C?+語言提供了一種新的單行注釋形式://ExplanationSentence即用"〃"表示注釋開始,從該位置直到當前行結束的所有字符都被作為注釋。舉個簡單的例子:/*下面的程序段計算從1到100的整數和,結果記錄在變量sum中sum=0://變量sum初值置為零for(i=1:i<=100;i++){〃循環(huán)體開始sum+=i;//儂次累加i.更加靈活的變量說明在傳統(tǒng)的C語言中,局部變量的說明必須集中放在執(zhí)行代碼的前面,數據說明語句和執(zhí)行語句的混合將引起扁譯錯誤.而在C++中,可以在程序代碼塊的任何地方進行局部變量的說明,比如下面的代碼在C語言中是不正涌的,在C++語言中卻可以正常運行.for(inti=1:i<=100;i++);這樣做的好處是使變量的定義和它的使用集中在一起,意義一目了然..更加嚴格的函數原型說明C++摒棄了C語言對函數原型隨意簡化的方式,這種簡化是許多C語言程序錯誤的根源,C++語言要求編程者的函數提供完整的原型,包括全部參數的類型和返回值得說明.例如,有字符型和雙精度類型兩個參數、返回整型值的函數f,原型應該寫為:intf(char,double);而C語言中允許將這個原型寫成);*.在函數原型說明中,參數名可有可無,并且可以和函數定義中的參數名不一致..增加了函數重載機制重載是程序語言領域的重要概念。常規(guī)語言中最典型的例子是"+、-、X、/?等各種苴術運算符的重載,這些符號可以同時用來表示多種類型數據之間的運苴,這種對一個名字或一個符號賦予多重意義的情況就叫重我.C++語言增加了C語言所沒有的函數重載機制.對一個函數名可以給出多個函數定義,只要這些定義可以通過參數個數或類型的不同區(qū)別開來即可.C++還允許對系統(tǒng)中預先定義的運篁符號進行重載,增加新的定義.這樣做的優(yōu)點是在今后對新定義類型的變量進行運篁時,計篁公式寫起來方便自然..函數缺省參數C++中允許函數有缺省參數.所渭岐省,是指函數調用時可以不給出實際的參數值.下面是一個有缺省參數的函數定義的實例:intf(inta,intb=l)(returna*b;]此后,函數調用f(3,1)和f(3)將返回同樣的結果..輸入/輸出流機制C+*保留了C語言標準庫中各種輸入/輸出函數,而且提供了一套新的輸入/輸出機制一一流機制.比如向標法輸出輸出一個字符串:cout?*C++isbeautiful!*;或者由標準輸入讀一個整數,賦給變量ainta;cin?a;流式輸入/輸出運算符能夠根據變量類型自動確定數據交換過程中的轉換方式,還可以定義”《、>>”的重我,方便了銅程者自定義類型的數據的輸入/輸出..作用域限定運菖符::作用域限定運算符::用于對當前作用域之外的同名變量進行訪問.例如在下面的例子中,我們可以利用:實現(xiàn)在局部變量期作用域范圍內對全局變量有)訪問.#include<iostreamh>inta;voidmain。{floata;a=3.14;::a=6;cout?"localvariablea—cout?*globalvariableaa?endl;}程序執(zhí)行結果如下:localvariablea=3.14globalvariablea=6附錄2:C語言register關鍵字一最快的關鍵字register:這個關健字請求編譯器盡可能的將變量存在CPU內部寄存器中,而不是通過內存尋址訪問,以提高效率。注意是盡可能,不是絕對。你想想,一個CPU的寄存器也就那么幾個或幾十個,你要是定義了很多很多register變量,它累死也可能不能全部把這些變量放入寄存器吧,輪也可能輪不到你。一、皇帝身邊的小太監(jiān) 寄存器不知道什么是寄存器?那見過太監(jiān)沒有?沒有?其實我也沒有。沒見過不要緊,見過就麻煩大了。二~,大家都看過古裝戲,那些皇帝們要閱讀奏章的時候,大臣總是先將奏章交給皇帝旁邊的小太監(jiān),小太監(jiān)呢再交給皇帝同志處理。這個小太監(jiān)只是個中轉站,并無別的功能。好,那我們再聯(lián)想到我們的CPU。CPU不就是我們的皇帝同志么?大臣就相當于我們的內存,數據從他這拿出來。那小太監(jiān)就是我們的寄存器了(這里先不考慮CPU的高速緩存區(qū))。數據從內存里拿出來先放到寄存器,然后CPU再從寄存器里讀取數據來處理,處理完后同樣把數據通過寄存器存放到內存里,CPU不直接和內存打交道。這里要說明的一點是:小太監(jiān)是主動的從大臣手里接過奏章,然后主動的交給皇帝同志,但寄存器沒這么自覺,它從不主動干什么事。一個皇帝可能有好些小太監(jiān),那么一個CPU也可以有很多寄存器,不同型號的CPU擁有寄存器的數量不一樣。為啥要這么麻煩???速度!就是因為速度。寄存器其實就是一塊一塊小的存儲空間,只不過其存取速度要比內存快得多。進水樓臺先得月嘛,它離CPU很近,CPU一伸手就拿到數據了,比在那么大的一塊內存里去尋找某個地址上的數據是不是快多了?那有人問既然它速度那么快,那我們的內存硬盤都改成寄存器得了唄。我要說的是:你真有錢!二、舉例register修飾符暗示編譯程序相應的變量將被頻繁地使用,如果可能的話,應將其保存在CPU的寄存器中,以加快其存儲速度。例如下面的內存塊拷貝代碼,ttifdefNOSTRUCTASSIGNmemcpy(d,s,1)(registerchar*d;registerchar*s;registerinti;while(i-)*d++=*s++;)#endif三、使用register修飾符的注意點但是使用register修飾符有幾點限制。首先,register變量必須是能被CPU所接受的類型。這通常意味著register變量必須是一個單個的值,并且長度應該小于或者等于整型的長度不過,有些機器的寄存器也能存放浮點數。其次,因為register變量可能不存放在內存中,所以不能用來獲取register變量的地址。由于寄存器的數量有限,而且某些寄存器只能接受特定類型的數據(如指針和浮點數),因此真正起作用的register修飾符的數目和類型都依賴于運行程序的機器,而任何多余的register修飾符都將被編譯程序所忽略。在某些情況下,把變量保存在寄存器中反而會降低程序的運行速度。因為被占用的寄存器不能再用于其它目的;或者變量被使用的次數不夠多,不足以裝入和存儲變量所帶來的額外開銷。早期的C編譯程序不會把變量保存在寄存器中,除非你命令它這樣做,這時register修飾符是C語言的一種很有價值的補充。然而,隨著編譯程序設計技術的進步,在決定那些變量應該被存到寄存器中時,現(xiàn)在的C編譯環(huán)境能比程序員做出更好的決定。實際上,許多編譯程序都會忽略register修飾符,因為盡管它完全合法,但它僅僅是暗示而不是命令。9作業(yè)及強化訓練1復雜數據類型引用做函數參數分析內存四區(qū)變化圖2代碼敲一遍3設計一個類,求圓形的周長4設計一個學生類,屬性有姓名和學號,可以給姓名和學號賦值可以顯示學生的姓名和學號2、類和對象1前言C++學習技術路線及目標研究C++編譯器管理類和對象的方法===》避免死角C++編譯器對類對象的生命周期管理,對象創(chuàng)建、使用、銷毀C++面向對象模型初探C++面向對象多態(tài)原理探究操作符重載C++基礎課程學習完畢以后,有沒有一個標準,來判斷自己有沒有入門。面向抽象類(接口)編程C++面向編程思想工具..面向抽象類編程C++面向編程思想工具..面向抽象類編程(面向接口/軟件分層)2類和對象基本概念1)類、對象、成員變量、成員函數2)面向對象三大概念封裝、繼承、多態(tài)3)編程實踐類的定義和對象的定義,對象的使用求圓形的面積定義Teacher類,打印Teacher的信息(把類的聲明和類的實現(xiàn)分開)類的封裝1)封裝(Encapsulation)A)封裝,是面向對象程序設計最基本的特性。把數據(屬性)和函數(操作)合成一個整體,這在計算機世界中是用類與對象實現(xiàn)的。B)封裝,把客觀事物封裝成抽象的類,并且類可以把自己的數據和方法只讓可信的類或者對象操作,對不可信的進行信息隱藏。備注:有2層含義(把屬性和方法進行封裝對屬性和方法進行訪問控制)C++中類的封裝成員變量,C++中用于表示類屬性的變量成員函數,C++中用于表示類行為的函數2)類成員的訪問控制在C++中可以給成員變量和成員函數定義訪問級別Public修飾成員變量和成員函數可以在類的內部和類的外部被訪問Private修飾成員變量和成員函數只能在類的內部被訪問〃類是把屬性和方法封裝同時對信息進行訪問控制〃類的內部,類的外部〃我們抽象了一個類,用類去定義對象〃類是一個數據類型,類是抽象的〃對象是一個具體的變量。。占用內存空間。classCircle{public:doubler;doubles;public:doublegetR()(a++;returnr;}voidsetR(doubleval)(r=val;)public:doublegetS()〃增力口功能時,是在修改類,修改類中的屬性或者是方法s=3.14f*r*r;returns;}//private:inta;3)struct和class關鍵字區(qū)別在用struct定義類時,所有成員的默認屬性為public在用class定義類時,所有成員的默認屬性為privateC++面向對象程序設計舉例目標:面向過程向面向對象思想轉變初學者要仔細體會類和對象之間的關系,并通過適當練習鞏固和提高!案例1設計立方體類(cube),求出立方體的面積和體積求兩個立方體,是否相等(全局函數和成員函數)案例2設14■個圓形類(AdvCircle),和一個點類(Point),計算點在圓內部還是圓外即:求點和圓的關系(圓內和圓外)案例3對于第二個案例,類的聲明和類的實現(xiàn)分開作業(yè)作業(yè)1:編寫C++程序完成以下功能:1)定義一個Point類,其屬性包括點的坐標,提供計算兩點之間距離的方法;2)定義?個圓形類,其屬性包括圓心和半徑;3)創(chuàng)建兩個圓形對象,提示用戶輸入圓心坐標和半徑,判斷兩個圓是否相交,并輸出結果。作業(yè)2:設計并測試一個名為Rectangle的矩形類,其屬性為矩形的左下角與右上角兩個點的坐標,根據坐標能計算出矩形的面積作業(yè)3:定義一個Tree類,有成員ages(樹齡),成員函數grow(intyears)對ages加上years,age()顯示tree對象的ages的值。3對象的構造和析構前言創(chuàng)建一個對象時,常常需要作某些初始化的工作,例如對數據成員賦初值。注意,類的數據成員是不能在聲明類時初始化的。為了解決這個問題,C++編譯器提供了構造函數(constructor)來處理對象的初始化。構造函數是一種特殊的成員函數,與其他成員函數不同,不需要用戶來調用它,而是在建立對象時自動執(zhí)行。3.1構造和析構函數1構造函數和析構函數的概念有關構造函數1構造函數定義及調用1)C++中的類可以定義與類名相同的特殊成員函數,這種與類名相同的成員函數叫做構造函數:2)構造函數在定義時可以有參數;3)沒有任何返回類型的聲明。2構造函數的調用自動調用:一般情況下C++編譯器會自動調用構造函數手動調用:在一些情況下則需要手工調用構造函數有關析構函數3)析構函數定義及調用1)C++中的類可以定義一個特殊的成員函數清理對象,這個特殊的成員函數叫做析構函數語法:~ClassName()2)析構函數沒有參數也沒有任何返回類型的聲明3)析構函數在對象銷毀時自動被調用4)析構函數調用機制C++編譯器自動調用代碼演示:dm01_構造函數的基礎.cpp2C++編譯器構造析構方案PK對象顯示初始化方案設計構造函數和析構函數的原因面向對象的思想是從生活中來,手機、車出廠時,是一樣的。生活中存在的對象都是被初始化后才上市的:初始狀態(tài)是對象普遍存在的一個狀態(tài)的普通方案:為每個類都提供一個public的initialize函數:對象創(chuàng)建后立即調用initialize函數進行初始化。優(yōu)缺點分析initialize只是一個普通的函數,必須顯示的調用一旦由于失誤的原因,對象沒有初始化,那么結果將是不確定的沒有初始化的對象,其內部成員變量的值是不定的3)不能完全解決問題〃為什么對象需要初始化有什么樣的初始化方案#include"iostream"usingnamespacestd;/*思考為什么需要初始化面向對象思想來自生活,手機、車、電子產品,出廠時有初始化怎么樣進行初始化?方案1:顯不調用方法缺點:易忘、麻煩;顯示調用init,不能完全解決問題*/classTest21(public:intm;intgetM()const{returnm;}voidsetM(intval){m=val;}intn;intgetN()const{returnn;}voidsetN(intval){n=val;}public:intinit(intmjntn)(this->m=m;this->n=n;return0;}protected:private:};intmain(){intrv=0;Test21tl;〃無參構造函數的調用方法Test2112;//tl.init(100z200);//t2.init(300z400);cout?tl.getM()?""?tl.getN()?endl;cout?t2.getM()?""?t2.getN()?endl;〃定義對象數組時,沒有機會進行顯示初始化Test21arr[3];//Testarr__2[3]={Test(l,3),Test。,Test。};system("pausen);returnrv;|3.2構造函數的分類及調用C++編譯器給程序員提供的對象初始化方案,高端大氣上檔次?!ㄓ袇禈嬙旌瘮档娜N調用方法classTestprivate:inta;intb;public:〃無參數構造函數Test()〃帶參數的構造函數Test(inta,intb)(>}〃賦值構造函數Test(constTest&obj)public:voidinit(int_azint_b)(a=_a;b=__b;)1無參數構造函數調用方法:Testtl,t2;2有參構造函數有參構造函數的三種調用方法〃有參數構造函數的三種調用方法classTests(private:inta;public:〃帶參數的構造函數Test5(inta)printf("\na:%d",a);}Test5(inta,intb){printf("\na:%db:%d",a,b);}public:);intmain55()(Test5tl(10);〃c++編譯器默認調用有參構造函數括號法Test5t2=(20,10);〃c++編譯器默認調用有參構造函數等號法Test5t3=Test5(30);〃程序員手工調用構造函數產生了一個對象直接調用構造構造函數法system("pause");return0;3拷貝構造函數調用時機賦值構造函數的四種調用場景(調用時機)第1和笫2個調用場景#include"iostream"usingnamespacestd;classAApublic:AA()〃無參構造函數默認構造函數{cout<〈"我是構造函數,自動被調用了"<<endl;}AA(int_a)〃無參構造函數默認構造函數{a=_a;}AA(constAA&obj2)(cout<<"我也是構造函數,我是通過另外一個對象obj2,來初始化我自己"<<endl;a=obj2.a+10;}~AA()(cout<〈"我是析構函數,自動被調用了"<<endl;}voidgetA()printf("a:%d\n",a);protected:private:inta;);〃單獨搭建一個舞臺voidObjPlay01(){AAal;〃變量定義〃賦值構造函數的第一個應用場景〃用對象1初始化對象2AAa2=al;〃定義變量并初始化〃初始化法a2=al;〃用al來=號給a2編譯器給我們提供的淺copy第二個應用場景〃單獨搭建一個舞臺voidObjPlay02()AAal(10);〃變量定義〃賦值構造函數的第一個應用場景〃用對象1初始化對象2AAa2(al);〃定義變量并初始化〃括號法〃a2=al;〃用al來=號給a2編譯器給我們提供的淺copya2.getA();}〃注意:初始化操作和等號操作是兩個不同的概念第3個調用場景#include"iostream"usingnamespacestd;classLocation(public:Location(intxx=0,intyy=0){X=xx;Y=yy;cout?"ConstructorObject.\n";)Location(constLocation&p) 〃復制構造函數{X=p.X;Y=p.Y;cout?"Copy_constructorcalled."?endl;)~Location()cout?X?Mz"?Y?"Objectdestroyed."?endl;}intGetX(){returnX;}intGetY(){returnY;}private:intX,Y;};//alt+f8排版voidf(Locationp)(cout?"Funtion:"?p.GetX()? ?p.GetY()?endl;}voidmainobjplay()(LocationA(1,2);〃形參是一個元素,函數調用,會執(zhí)行實參變量初始化形參變量f(A);}voidmain(){mainobjplay();system("pause");第4個調用場景第四個應用場景tfinclude"iostream"usingnamespacestd;classLocation(public:Location(intxx=0,intyy=0){X=xx;Y=yy;cout?"ConstructorObject.\n";)Location(constLocation&p) 〃復制構造函數(X=p.X;Y=p.Y;cout?"Copy_constructorcalled."?endl;}?Location。(cout?X? ?Y?“Objectdestroyed."?endl;)intGetX(){returnX;} intGetY(){returnY;}private:intX,Y;);//alt+f8排版voidf(Locationp)(cout?"Funtion:"?p.GetX()?"/*?p.GetY()?endl;)Locationg(){LocationA(l,2);returnA;|〃對象初始化操作和=等號操作是兩個不同的概念〃匿名對象的去和留,關鍵看,返回時如何接voidmainobjplay()(〃若返回的匿名對象,賦值給另外一個同類型的對象,那么匿名對象會被析構//LocationB;//B=g();〃用匿名對象賦值給B對象,然后匿名對象析構〃若返回的匿名對象,來初始化另外一個同類型的對象,那么匿名對象會直接轉成新的對象LocationB=g();cout<<"傳智掃地僧測試"<<endl;}

voidmain()(mainobjplay();system("pause");柱用a睛家創(chuàng)建了一個IS用a睛家創(chuàng)建了一個ISprintf「因為用片名對獴紛?2,店名對象,被折構VT).cout<<a2.GetX()<<end1..返何的黑一個新E轉成有名對象抬名對象械新構〃緒論1:函數的返向值整個元素(復雜類型的),對象類的copy痂選返何的黑一個新E轉成有名對象抬名對象械新構//〃結論2:有關歌名對象的去和留〃如果用店名對象初始化另外一個同類型的睛象.〃如果用£名對象賦值給另外個同類型的對做,4默認構造函數二個特殊的構造函數1)默認無參構造函數當類中沒有定義構造函數時,編譯器默認提供一個無參構造函數,并且其函數體為空2)默認拷貝構造函數當類中沒有定義拷貝構造函數時,編譯器默認提供一個默認拷貝構造函數,簡單的進行成員變量的值復制3.3構造函數調用規(guī)則研究1)當類中沒有定義任何一個構造函數時,C++編譯器會提供默認無參構造函數和默認拷貝構造函數2)當類中定義了拷貝構造函數時,C++編譯器不會提供無參數構造函數當類中定義了任意的非拷貝構造函數(

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論