C++语法知识复习2(黑马程序员教程P109-p146)
C++學習
- 1、類和對象
- P109 析構函數調用規則
- p110 深拷貝與淺拷貝
- p111 初始化列表
- p112 類對象作為類成員
- p113 靜態成員
- p114 成員變量與成員函數分開存儲
- p115 this指針(沒太聽懂¥¥¥¥¥¥¥)
- **按引用返回,返回是對象本身。。。按值方式返回,返回的不是對象本體,而是調用拷貝(負責)構造函數新建的一個對象,見復習1文檔的最后內容**
- **按引用返回,返回是對象本身。。。按值方式返回,返回的不是對象本體,而是調用拷貝(負責)構造函數新建的一個對象,見復習1文檔的最后內容**
- **按引用返回,返回是對象本身。。。按值方式返回,返回的不是對象本體,而是調用拷貝(負責)構造函數新建的一個對象,見復習1文檔的最后內容**
- p116 空指針訪問成員函數
- p117 Const修飾成員函數
- p118 全局函數 做友元
- p119 讓類做友元
- p120 成員函數做友元
- p121 加法運算符重載
- p122 左移運算符重載
- p123 遞增運算符重載
- p124 賦值運算法重載
- p125 關系運算符重載
- p126函數調用運算符重載
- p127 繼承-基本語法(重點)
- p128繼承方式
- p129 繼承中的對象模型
- p130 構造和析構順序
- p131 繼承中同名函數處理方式
- p132 繼承同名靜態成員函數處理方式
- p133 多繼承語法
- p134 菱形繼承或者鉆石繼承
- p135 多態的基本語法
- p136
- p137 多態案例
- p138 純虛函數和抽象類
- p139 多態 案例
- p140 虛析構 純虛析構
- p142 案例
- p143文件操作-文本文件-寫文件
- p144文件操作-文本文件-讀文件
- p145 p146 二進制文件的讀取和寫入
1、類和對象
P109 析構函數調用規則
因為默認構造函數對其屬性進行了拷貝
p110 深拷貝與淺拷貝
復制(拷貝)構造函數,形參必須是本類對象的引用。若類中沒有定義復制構造函數,系統會定義一個默認的復制構造函數,完成將一個對象的所有數據成員復制(拷貝)到另一個對象的相應數據成員中。也就是淺拷貝。
復制(拷貝)構造函數,形參必須是本類對象的引用。若類中沒有定義復制構造函數,系統會定義一個默認的復制構造函數,完成將一個對象的所有數據成員復制(拷貝)到另一個對象的相應數據成員中。也就是淺拷貝。
復制(拷貝)構造函數,形參必須是本類對象的引用。若類中沒有定義復制構造函數,系統會定義一個默認的復制構造函數,完成將一個對象的所有數據成員復制(拷貝)到另一個對象的相應數據成員中。也就是淺拷貝。
復制(拷貝)構造函數,形參必須是本類對象的引用。若類中沒有定義復制構造函數,系統會定義一個默認的復制構造函數,完成將一個對象的所有數據成員復制(拷貝)到另一個對象的相應數據成員中。也就是淺拷貝。
復制(拷貝)構造函數,形參必須是本類對象的引用。若類中沒有定義復制構造函數,系統會定義一個默認的復制構造函數,完成將一個對象的所有數據成員復制(拷貝)到另一個對象的相應數據成員中。也就是淺拷貝。
復制(拷貝)構造函數,形參必須是本類對象的引用。若類中沒有定義復制構造函數,系統會定義一個默認的復制構造函數,完成將一個對象的所有數據成員復制(拷貝)到另一個對象的相應數據成員中。也就是淺拷貝。
復制(拷貝)構造函數,形參必須是本類對象的引用。若類中沒有定義復制構造函數,系統會定義一個默認的復制構造函數,完成將一個對象的所有數據成員復制(拷貝)到另一個對象的相應數據成員中。也就是淺拷貝。
深拷貝與淺拷貝
淺拷貝:編譯器做的簡單賦值操作叫做淺拷貝
堆區開辟的數據由程序員手動開辟,也需要程序員手動釋放
test01() 執行完 對象p1p2就被銷毀了
在對象p1p2銷毀前需要將堆區數據釋放,p1p2對象銷毀前會調用 析構函數
因此可以使用析構函數釋放堆區數據
因為p1p2是局部變量(對象),所以在棧上,棧上的規則就是先進后出
因為p1p2是局部變量(對象),所以在棧上,棧上的規則就是先進后出
因為p1p2是局部變量(對象),所以在棧上,棧上的規則就是先進后出
因為p1p2是局部變量(對象),所以在棧上,棧上的規則就是先進后出
因為p1p2是局部變量(對象),所以在棧上,棧上的規則就是先進后出
因為p1p2是局部變量(對象),所以在棧上,棧上的規則就是先進后出
所以對象p2先被釋放,先執行p2的析構函數
編譯的會出現問題,出現問題的原因如下::
tips:vscode可能對于這個例子不會蹦
存放的數據一樣,但是指針指向的內存不一樣
重新在堆區找塊內存存放,也就是說存放的內容(160)一樣,但是內存也就是地址不一樣
這就叫深拷貝
自定義編寫拷貝構造函數,完成深拷貝。
自定義編寫拷貝構造函數,完成深拷貝。
自定義編寫拷貝構造函數,完成深拷貝。
自定義編寫拷貝構造函數,完成深拷貝。
自定義編寫拷貝構造函數,完成深拷貝。
這樣的話,析構的時候,各自釋放各自的堆區內存,因為內存不一樣了。所以肯定不會出現重復釋放內存(也就是地址)的問題
淺拷貝是編譯器根據默認拷貝構造函數自動完成的
p111 初始化列表
p112 類對象作為類成員
A是類(也就是自定義的數據類型)
a是對象成員,數據類型為A
對象成員也可以使用初始化列表的方式進行初始化,可能會使用到構造函數調用中的 隱世轉換法
#include <iostream>using namespace std; #include <string>//手機類 class Phone {public:Phone(string name) :m_pName(name){cout << "手機類構造函數的調用" << endl;}~Phone(){cout << "Phone的析構函數" << endl;}string m_pName; };//人類 class Person {public://后面那個初始化相當于Phone m_phone = pname 也就是隱世轉換調用Person(string name, string pname) :m_name(name), m_phone(pname){cout << "人類構造函數的調用" << endl;}~Person(){cout << "Person的析構函數" << endl;}//姓名string m_name;//手機Phone m_phone; };void test01() {Person p1("張帥", "華為");cout << p1.m_name << "使用" << p1.m_phone.m_pName << endl; }int main() {test01();return 0; }當其他類對象作為本類成員時,構造時先構造其他類對象,再構造本類對象,析構的順序與構造的順序相反
p113 靜態成員
1、所有對象共享一份數據,對象a的這個數據變化后,對象b調用這個數據時也變化了。
2、在編譯階段分配內存:也就是指:程序還沒有運行之前,(程序編譯后,)生成exe還沒有雙擊之前就已經分配好內存了,放在全局區里面
靜態成員變量,不屬于某個對象上,所有的對象都共享同一份數據
靜態成員變量,不屬于某個對象上,所有的對象都共享同一份數據
靜態成員變量,不屬于某個對象上,所有的對象都共享同一份數據
教程連接
p114 成員變量與成員函數分開存儲
p115 this指針(沒太聽懂¥¥¥¥¥¥¥)
this指針指向 被調用的成員函數所屬的對象
this指針指向 被調用的成員函數所屬的對象
this指針指向 被調用的成員函數所屬的對象
this指針指向 被調用的成員函數所屬的對象
this指針指向 被調用的成員函數所屬的對象
this指針指向 被調用的成員函數所屬的對象
this指針指向 被調用的成員函數所屬的對象
1、解決名稱沖突
2、返回對象本身用*this
按引用返回,返回是對象本身。。。按值方式返回,返回的不是對象本體,而是調用拷貝(負責)構造函數新建的一個對象,見復習1文檔的最后內容
按引用返回,返回是對象本身。。。按值方式返回,返回的不是對象本體,而是調用拷貝(負責)構造函數新建的一個對象,見復習1文檔的最后內容
按引用返回,返回是對象本身。。。按值方式返回,返回的不是對象本體,而是調用拷貝(負責)構造函數新建的一個對象,見復習1文檔的最后內容
我明白了
之所以用引用返回的方式,是因為疊加是在原數據(也就是p2)改變的基礎上遞增,所以用引用。
如果去掉引用返回,也就是去掉&后,每一次調用都會返回一個新的對象(因為值方式返回的原因,每一次調用后返回的都是一個新的對象,調用了拷貝構造函數,最后也就不是p2了,而是p2\\)
如下:
所以最后輸出的時候,p2.age只加了一次而不是三次。
總結:此例子中,如果值方式返回則:會創建新的對象。如果引用方式返回,則:不會創建新的對象,一直都是p2。
有了*this 就可以使用連式編程思想進行編程
有了*this 就可以使用連式編程思想進行編程
有了*this 就可以使用連式編程思想進行編程
有了*this 就可以使用連式編程思想進行編程
p116 空指針訪問成員函數
p117 Const修飾成員函數
下圖的函數即為常函數:
p118 全局函數 做友元
第一種情況:用全局函數作為好朋友
只要上面的那條語句寫到類中最上面就可以了,也不需要public啥的
p119 讓類做友元
第二中情況,讓類做友元
p120 成員函數做友元
第三種情況: 讓成員函數做友元
成員函數類外實現或類內實現都可以
#include <iostream>#include <string>using namespace std;class Building;//先聲明類Building class GoodGay//定義類 {public:GoodGay();void visit1(); //讓visit函數可以訪問Building中的私有成員void visit2();//讓visit2函數不可以訪問Building中的私有成員Building *building; };class Building {friend void GoodGay::visit1();public:Building();string m_SittingRoom;private:string m_BedRoom; }; //類外寫成員函數 GoodGay::GoodGay() {//創建建筑物對 創建一個Building對象在堆區building = new Building; } //類外寫成員函數 void GoodGay::visit1() {cout << "visit1正在訪問" << building->m_SittingRoom << endl;cout << "visit1正在訪問" << building->m_BedRoom << endl;}void GoodGay::visit2() {cout << "visit2正在訪問" << building->m_SittingRoom << endl;// cout << "正在訪問" << building->m_BedRoom << endl;} //類外寫成員函數 Building::Building() {m_BedRoom = "臥室";m_SittingRoom = "客廳"; }void test01() {GoodGay gg;gg.visit1();gg.visit2(); }int main() {test01();return 0; }
如果不是友元,那么只能訪問公共屬性
p121 加法運算符重載
兩種重載方式,一種是成員函數,另一種是全局函數
兩種方式的重載本質調用
運算符也可以發生函數重載
函數重載的概念回憶一下::
p122 左移運算符重載
一般不使用第一種方式,也就是成員函數實現重載,原因如下:
cout:標準的輸出流對象 類:ostream
cin: 標準的輸入流對象 類:istream
因為cout對象全局只有一個,所以需要引用的方式傳遞進來,值傳遞的話,就會創建(復制一個副本)一個新的對象。
輸出流不能拷貝,也就是說要傳入輸出流對象參數只能地址傳遞,不能值傳遞。
流對象不能復制只能引用,記住就好了
輸出流不能拷貝,也就是說要傳入輸出流對象參數只能地址傳遞,不能值傳遞。
流對象不能復制只能引用,記住就好了
輸出流不能拷貝,也就是說要傳入輸出流對象參數只能地址傳遞,不能值傳遞。
流對象不能復制只能引用,記住就好了
輸出流不能拷貝,也就是說要傳入輸出流對象參數只能地址傳遞,不能值傳遞。
流對象不能復制只能引用,記住就好了
輸出流不能拷貝,也就是說要傳入輸出流對象參數只能地址傳遞,不能值傳遞。
流對象不能復制只能引用,記住就好了
輸出流不能拷貝,也就是說要傳入輸出流對象參數只能地址傳遞,不能值傳遞。
流對象不能復制只能引用,記住就好了
p123 遞增運算符重載
內置的遞增++運算符:
前置遞增 先對變量進行遞增,再進行其他操作。
后置遞增,先對變量進行完其他操作,再進行變量遞增。
1、前置遞增
返回引用是為了一直對一個對象進行遞增操作,否則的話,如果不是返回引用,而是返回值,則每次遞增后返回一個新的對象(調用拷貝構造函數,如果沒有自己定義的,會進行淺拷貝)。
返回引用是為了一直對一個對象進行遞增操作,否則的話,如果不是返回引用,而是返回值,則每次遞增后返回一個新的對象(調用拷貝構造函數,如果沒有自己定義的,會進行淺拷貝)。
返回引用是為了一直對一個對象進行遞增操作,否則的話,如果不是返回引用,而是返回值,則每次遞增后返回一個新的對象(調用拷貝構造函數,如果沒有自己定義的,會進行淺拷貝)。
嗶哩嗶哩鏈接
對象作為返回值不加引用就會調用拷貝構造函數
對象作為返回值不加引用就會調用拷貝構造函數
對象作為返回值不加引用就會調用拷貝構造函數
對象作為返回值不加引用就會調用拷貝構造函數
對象作為返回值不加引用就會調用拷貝構造函數
對象作為返回值不加引用就會調用拷貝構造函數
對象作為返回值不加引用就會調用拷貝構造函數
對象作為返回值不加引用就會調用拷貝構造函數
復習知識點:拷貝構造函數的調用時機
值返回是相當于對一個新的返回,再操作又繼續開個新的重復
2、后置遞增
返回值不可以作為函數重載的條件
函數占位參數
此例中的移位與上一節課中的不太一樣
后置++使用移位運算符重載 不能定義引用 ,因為返回的臨時對象temp已被編譯器釋放,因此只能值傳遞
p124 賦值運算法重載
一般來說,只要是值拷貝,都會引發深淺拷貝問題
回憶:拷貝構造函數
讓p2=p1之后,再把p2這個對象傳給p3,也就是函數operator=調用完之后還能返回自身(使用return *this返回自身)
返回本體需要時引用返回,而不是值返回
此例中若返回值的話,那就是按照自身調用一個拷貝構造函數(默認淺拷貝),創建一個新的對象(副本),而不是對象自身了。我們要返回其引用才是其真正的自身。
p125 關系運算符重載
#include <iostream> #include <string>using namespace std;class Person {public:Person(string name,int age){m_Age = age;m_Name = name;}bool operator==(Person &p){if (this->m_Age==p.m_Age && this->m_Name==p.m_Name){return true;}else{return false;}}string m_Name;int m_Age; };void test01() {Person p1("tom1", 22);Person p2("tom", 22);if(p1==p2){cout << "yes" << endl;}else{cout << "no" << endl;} }int main() {test01();return 0; }p126函數調用運算符重載
仿函數
十分靈活
匿名函數對象
p127 繼承-基本語法(重點)
繼承的技術
p128繼承方式
p129 繼承中的對象模型
開發人員命令提示工具
p130 構造和析構順序
p131 繼承中同名函數處理方式
注意是所有的同名函數(包括重載的 都給隱藏掉了)
p132 繼承同名靜態成員函數處理方式
復習 類與對象中的靜態成員
靜態成員的訪問有兩種方式:通過對象訪問或者通過類名。
靜態成員的訪問有兩種方式:通過對象訪問或者通過類名。
靜態成員的訪問有兩種方式:通過對象訪問或者通過類名。
靜態成員的訪問有兩種方式:通過對象訪問或者通過類名。
靜態成員的訪問有兩種方式:通過對象訪問或者通過類名。
靜態成員的訪問有兩種方式:通過對象訪問或者通過類名。
靜態成員的訪問有兩種方式:通過對象訪問或者通過類名。
靜態成員的訪問有兩種方式:通過對象訪問或者通過類名。
靜態成員的訪問有兩種方式:通過對象訪問或者通過類名。
1、通過對象訪問
2、通過類名訪問
p133 多繼承語法
作用域::
p134 菱形繼承或者鉆石繼承
【暫時沒學習,用到的時候再學習】
p135 多態的基本語法
父類引用指向子類對象
c++中運行父子類之間類型轉換
靜態多態
這樣就可以實現地址晚綁定 也就是動態多態
函數重寫的意思:(子類的virtual可寫可不寫)
總結:
p136
四個字節一般是整形變量 指針等
當用父類指針或者引用指向子類對象,調用speak時會調用小貓會說話。
p137 多態案例
p138 純虛函數和抽象類
p139 多態 案例
**
**
p140 虛析構 純虛析構
純虛析構函數需要注意的問題
在多態使用中:
不管是虛析構還是純虛析構 都是為了解決子類中析構代碼調用不到的問題
p142 案例
#include <iostream>using namespace std;//多態的使用 //多態案例//三個抽象類//cpu抽象類 class Cpu {public:virtual void Calculator() = 0; }; //顯卡抽象類 class VideoCard {public:virtual void display() = 0; }; //存儲抽象類 class Memory {public:virtual void storage() = 0; };//電腦類 class Computer {public://構造函數Computer(Cpu *cpu, VideoCard *vc, Memory *mem){cout << "Computer的構造" << endl;m_cpu = cpu;m_vc = vc;m_mem = mem;}void Work(){m_cpu->Calculator();m_mem->storage();m_vc->display();}//析構函數~Computer(){cout << "Computer的析構" << endl;if(m_cpu!=NULL){delete m_cpu;m_cpu = NULL;}if(m_vc!=NULL){delete m_vc;m_vc = NULL;}if(m_mem!=NULL){delete m_mem;m_mem = NULL;}}private : Cpu *m_cpu;VideoCard *m_vc;Memory *m_mem; };//Intel廠商 class IntelCpu : public Cpu {public://派生類重寫函數void Calculator(){cout << "Intel的cpu開始計算了" << endl;} }; class IntelVideoCard : public VideoCard {public:void display(){cout << "Intel的顯卡開始工作了" << endl;} }; class IntelMemory : public Memory {public:void storage(){cout << "Intel的內存開始工作了" << endl;} };//Lenovo廠商 class LenovoCpu : public Cpu {public:void Calculator(){cout << "Lenovo的cpu開始計算了" << endl;} }; class LenovoVideoCard : public VideoCard {public:void display(){cout << "Lenovo的顯卡開始工作了" << endl;} }; class LenovoMemory : public Memory {public:void storage(){cout << "Lenovo的內存開始工作了" << endl;} };void test01() {//第一臺電腦零件//多態的條件之一,父類指針指向子類對象//堆區的數據手動開啟 需要手動釋放!!!!!!Cpu *intelCpu = new IntelCpu;VideoCard *videoCard = new IntelVideoCard;Memory *memory = new IntelMemory;//創建第一臺電腦Computer *computer = new Computer(intelCpu, videoCard, memory);computer->Work();//釋放下面這個對象時 執行器析構函數delete computer;//創建第二臺電腦 換了個寫法 直接在實參出new ,,,Computer *computer2 = new Computer(new LenovoCpu, new LenovoVideoCard, new LenovoMemory);computer2->Work();delete computer2; }int main() {test01();return 0; }p143文件操作-文本文件-寫文件
五步法寫文件
p144文件操作-文本文件-讀文件
讀文件共有四種方式,第四種如下:
p145 p146 二進制文件的讀取和寫入
=暫時未學習
總結
以上是生活随笔為你收集整理的C++语法知识复习2(黑马程序员教程P109-p146)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Wincc V7.3SE安装截图
- 下一篇: linux 分卷压缩到指定目录,运用在a