孫鑫視訊---掌握C++
C++經典語法與應用,類的編寫與應用,構造與解構函式,函式的過載,類的繼承,函式覆蓋,基類與派生類的建構函式、解構函式先後呼叫順序,如何在派生類建構函式中向基類的建構函式傳遞引數,this成員變數,型別轉換的內幕,虛擬函式與多型性,引用和指標的變數的區別與共同處。
VC工程的編譯原理與過程,將工程中不同的類拆分到不同的原檔案中,每一個類由一個.h和.cpp檔案共同完成,標頭檔案重複定義問題的解決,培養了學員良好的程式設計習慣,也為以後分析MFC Appwizard生成的工程奠定了良好基礎。
C++的標準輸入輸出流
C++中提供了一套輸入輸出流類的物件,它們是cin 、cout和cerr,對應c語言中的三個檔案指標stdin、stdout、stderr,分別指向終端輸入、終端輸出和標準出錯輸出(也從終端輸出)。
cin與>>一起完成輸入操作,cout、cerr與<<一起完成輸出與標準錯誤輸出。
利用cin和cout比C語言中的scanf和printf要方便得多,cin和cout可以自動判別輸入輸出資料型別而自動調整輸入輸出格式,不必像scanf和printf那樣一個個由使用者指定。使用cin,cout不僅方便,而且減少了出錯的可能性。
對於輸出來說,我們像以上方式呼叫就可以了,對於輸入來說,我們以如下方式呼叫即可:
int i; cin>>i;
注意箭頭的方向。在輸出中我們還使用endl(end of line),表示換行,注意最後一個是字元‘l’,而不是數字1,endl相當於C語言的'\n',表示輸出一個換行。
#include <iostream> using namespace std; //定義結構體 //struct Point class Point { public://表示所有資料成員都可以在外部訪問 //private:私有,對外資料成員都不可訪問 //protected:子類和父類之間的訪問 int x; int y; void output() { cout<<x<<endl<<y<<endl; } }; void main() { Point pt; pt.x=5; pt.y=5; //cout<<pt.x<<endl<<pt.y<<endl; pt.output(); }
建構函式
1、建構函式最重要的作用是建立物件本身
2、C++規定,每個類必須有一個建構函式,沒有建構函式,就不能建立任何物件
3、C++又規定,如果一個類沒有提供任何的建構函式,則C++提供一個預設的建構函式(由C++編譯器提供),這個預設的建構函式是一個不帶引數的建構函式,它只負責建立物件,而不做任何的初始化工作
4、只要一個類定義了一個建構函式,不管這個建構函式是否是帶引數的建構函式,C++就不再提供預設的建構函式。也就是說,如果為一個類定義了一個帶引數的建構函式,還想要無引數的建構函式,則必須自己定義
#include <iostream> using namespace std; //定義結構體 //struct Point class Point { public://表示所有資料成員都可以在外部訪問 int x; int y; /* void init() { x=0; y=0; };*/ Point()//建構函式,用於建立物件本身 { x=0; y=0; } void output() { cout<<x<<endl<<y<<endl; } }; void main() { Point pt;//例項化一個物件 //pt.init(); //pt.x=5; //pt.y=5; //cout<<pt.x<<endl<<pt.y<<endl; pt.output(); }
解構函式
1、當一個物件生命週期結束時,其所佔有的記憶體空間就要被回收,這個工作就由解構函式來完成。
2、解構函式是“反向”的建構函式,解構函式不允許有返回值,更重要的是解構函式不允許帶引數,並且一個類中只能有一個解構函式。
3、解構函式的作用正好與建構函式相反,物件超出其作用範圍,對應的記憶體空間被系統收回或被程式用delete刪除時,解構函式被呼叫。
4、根據解構函式的這種特點,我們可以在建構函式中初始化物件的某些成員變數,給其分配記憶體空間(堆記憶體),在解構函式中釋放物件執行期間所申請的資源。
#include <iostream> using namespace std; class Point { public://表示所有資料成員都可以在外部訪問 int x; int y; /* void init() { x=0; y=0; };*/ Point() { x=0; y=0; } ~Point()//解構函式,生命週期結束的時候呼叫這個函式進行空間釋放,系統自動完成 { } void output() { cout<<x<<endl<<y<<endl; } }; void main() { Point pt;//例項化一個物件 pt.output(); }
函式的過載
過載構成的條件:函式的引數型別、引數個數不同,才能構成函式的過載。
分析以下兩種情況,是否構成函式的過載。
第一種情況:(1)void output();
(2)int output();
只有返回值不同的兩個函式不能構成函式的過載
第二種情況:(1)void output(int a,int b=5);
(2)void output(int a);
帶預設值也是不能構成函式過載
this指標
1、this指標是一個隱含的指標,它是指向物件本身,代表了物件的地址
2、一個類所有的物件呼叫的成員函式都是同一程式碼段。那麼成員函式又是怎麼識別屬於同一物件的資料成員呢?
原來,在物件呼叫pt.output(10,10)時,成員函式除了接受2個實參外,還接受到了一個物件s的地址。這個地址被一個隱含的形參this指標所獲取,它等同於執行this=&pt
所有對資料成員的訪問都隱含地被加上字首this->。例如:x=0; 等價於 this->x=0
在以後的MFC程式設計中,如果在成員函式中想呼叫同類中的某個成員,可以使用VC++提供的自動列出成員函式功能,使用this->,VC++將列出該類中的所有成員,我們可以從列表中選擇我們想呼叫的成員。
自動列出成員函式功能,可以提高編寫速度,減少拼寫錯誤。我們經常不能完全記住某個函式的完整拼寫,但卻能夠從列表中辨別出該函式,自動列出成員函式的功能在這時就顯得更加有用了。
事實上,在各種IDE程式設計環境中,我們通常都不可能記住也沒有必要記住所有的函式,只要將常用的函式記住,其他不常用的函式只要記住其大概的寫法和功能,在呼叫該函式時可以從自動列出成員函式中選取,這樣可以大大節省我們的學習時間。
我們不用花費大量的時間去死記硬背許多函式,利用自動列出成員函式功能和幫助系統,就能夠在程式設計時順利地使用這些函式,等用的次數多了,也就在不知不覺中完全掌握了這些函式。
#include <iostream> using namespace std; class Point { public://表示所有資料成員都可以在外部訪問 int x; int y; /* void init() { x=0; y=0; };*/ Point() { x=0; y=0; } Point(int a,int b)//函式的過載 { x=a; y=b; } ~Point()//解構函式,生命週期結束的時候呼叫這個函式進行空間釋放,系統自動完成 { } void output() { cout<<x<<endl<<y<<endl; } void output(int x,int y) { this->x=x; this->y=y; } }; void main() { Point pt(3,3);//例項化一個物件 pt.output(5,5); pt.output(); }
類的繼承
在C++中,給我們提供了一種重要的機制,就是繼承。 理解繼承是理解面向物件程式設計的關鍵。
#include<iostream> using namespace std; class Animal { public: void eat() { cout<<"animal eat"<<endl; } void sleep() { cout<<"animal sleep"<<endl; } void breathe() { cout<<"animal breathe"<<endl; } }; class Fish:public Animal//Animal是基類(父類),Fish是派生類(子類) { }; void main() { Animal an; an.eat(); Fish fh; fh.sleep(); }
訪問許可權
#include<iostream> using namespace std; class Animal { public: void eat() { cout<<"animal eat"<<endl; } protected://保護,對於子類是可以訪問,在外部不可以被訪問 void sleep() { cout<<"animal sleep"<<endl; } private://私有方法,在子類中不可以訪問 void breathe() { cout<<"animal breathe"<<endl; } }; class Fish:public Animal//Animal是基類(父類),Fish是派生類(子類) { void test() { sleep(); //breathe(); } }; void main() { Animal an; an.eat(); Fish fh; //fh.sleep();//保護的方法不能在外部訪問 }
類的繼承訪問特性
#include<iostream> using namespace std; class Animal { public: Animal() { cout<<"animal construct"<<endl; } ~Animal() { cout<<"animal decconstruct"<<endl; } void eat() { cout<<"animal eat"<<endl; } void sleep() { cout<<"animal sleep"<<endl; } void breathe() { cout<<"animal breathe"<<endl; } }; class Fish:public Animal { public: Fish() { cout<<"fish construct"<<endl; } ~Fish() { cout<<"fish decconstruct"<<endl; } }; void main() { Fish fh; }
輸出結果:
函式的覆蓋
函式的覆蓋是發生在父類與子類之間
#include<iostream> using namespace std; class Animal { public: Animal(int height,int weight) { cout<<"animal construct"<<endl; } ~Animal() { cout<<"animal decconstruct"<<endl; } void eat() { cout<<"animal eat"<<endl; } void sleep() { cout<<"animal sleep"<<endl; } void breathe() { cout<<"animal breathe"<<endl; } }; class Fish:public Animal { public: Fish():Animal(400,300),a(1) { //cout<<"fish construct"<<endl; } ~Fish() { //cout<<"fish decconstruct"<<endl; } void breathe() { Animal::breathe();//::表示作用域識別符號,表示這個函式是屬於哪個類的 cout<<"fish bubble"<<endl; } private: const int a; }; void main() { Fish fh; fh.breathe(); }
輸出結果:
animal construct
animal breathe
fish bubble
animal decconstruct
函式的多型
多型性 當C++編譯器在編譯的時候,發現Animal類的breathe()函式是虛擬函式,這個時候C++就會採用遲繫結(late binding)的技術,在執行時,依據物件的型別(在程式中,我們傳遞的Fish類物件的地址)來確認呼叫的哪一個函式,這種能力就做C++的多型性。
#include<iostream> using namespace std; class Animal { public: Animal(int height,int weight) { //cout<<"animal construct"<<endl; } void eat() { cout<<"animal eat"<<endl; } void sleep() { cout<<"animal sleep"<<endl; } virtual void breathe() //多型性:virtual 定義虛擬函式 會採用遲繫結,子類如果有就呼叫子類的,子類如果沒有就呼叫父類的 { cout<<"animal breathe"<<endl; } }; class Fish:public Animal { public: Fish():Animal(400,300),a(1) { //cout<<"fish construct"<<endl; } ~Fish() { //cout<<"fish decconstruct"<<endl; } void breathe() { //Animal::breathe();//::表示作用域識別符號,表示這個函式是屬於哪個類的 cout<<"fish bubble"<<endl; } private: const int a; }; void fn(Animal *pAn) { pAn->breathe(); } void main() { Fish fh; Animal *pAn; pAn=&fh; fn(pAn); }
純虛擬函式 virtual void breathe()=0;
指被表明為不具體實現的虛成員函式
純虛擬函式讓類先具有操作的名稱而沒有具體的內容,讓派生類在繼承的時候,再具體給出定義