日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

笔记 黑马程序员C++教程从0到1入门编程——核心编程

發(fā)布時(shí)間:2023/12/20 c/c++ 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 笔记 黑马程序员C++教程从0到1入门编程——核心编程 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

1 內(nèi)存分區(qū)模型

程序運(yùn)行前

01 代碼區(qū)

02 全局區(qū)

程序運(yùn)行后

03 棧區(qū)

04 堆區(qū)

05 new操作符

2 引用

06 引用的基本使用

07 引用注意事項(xiàng)

08 引用做函數(shù)參數(shù)

09 引用做函數(shù)返回值

10 引用的本質(zhì)

11 常量引用

3 函數(shù)提高

12函數(shù)默認(rèn)參數(shù)

13 函數(shù)占位參數(shù)

14 函數(shù)重載

4 類(lèi)和對(duì)象

封裝

16 封裝的意義 屬性和行為作為整體

對(duì)象特性:對(duì)象的初始化和清理

23 構(gòu)造函數(shù)和析構(gòu)函數(shù)

24 構(gòu)造函數(shù)的分類(lèi)和調(diào)用

?25 拷貝構(gòu)造函數(shù)調(diào)用時(shí)機(jī)

26 構(gòu)造函數(shù)調(diào)用規(guī)則

27 深拷貝和淺拷貝

28 初始化列表

29 類(lèi)對(duì)象作為類(lèi)成員

30 靜態(tài)成員

對(duì)象特性:C++對(duì)象模型和this指針

32 成員變量和成員函數(shù)分開(kāi)存儲(chǔ)

33 this指針

34 空指針訪(fǎng)問(wèn)成員函數(shù)

35 const修飾成員函數(shù)

友元

36 全局函數(shù)做友元

37 友元類(lèi)

38 成員函數(shù)做友元

C++運(yùn)算符重載

39 加號(hào)運(yùn)算符重載?

40 左移運(yùn)算符重載

41 遞增運(yùn)算符重載

42 賦值運(yùn)算符重載

43 關(guān)系運(yùn)算符重載

44 函數(shù)調(diào)用運(yùn)算符重載

繼承

45 基本語(yǔ)法

46 繼承方式

47 繼承中的對(duì)象模型

48 構(gòu)造和析構(gòu)順序

49 同名成員處理

50 同名靜態(tài)成員處理

51 多繼承語(yǔ)法

52 菱形繼承問(wèn)題以及解決方法

多態(tài)

53 多態(tài)的基本語(yǔ)法

54 多態(tài)的原理剖析

56 純虛函數(shù)和抽象函數(shù)

58 虛析構(gòu)和純虛析構(gòu)

5 文件操作

文本文件

143 寫(xiě)文件

144 讀文件

二進(jìn)制文件

145 寫(xiě)文件

146 讀文件


1 內(nèi)存分區(qū)模型

程序運(yùn)行前

程序運(yùn)行運(yùn)行前,編譯后:

01 代碼區(qū)

代碼區(qū):存放函數(shù)的二進(jìn)制代碼,有操作系統(tǒng)進(jìn)行管理
共享,只讀?

02 全局區(qū)

全局區(qū):存放全局變量靜態(tài)變量(static),常量(字符串常量const修飾的全局常量(全局常量))
【在程序結(jié)束后由操作系統(tǒng)釋放】
//不在全局區(qū)的數(shù)據(jù):局部變量、const修飾的局部變量(局部常量)?

程序運(yùn)行后

03 棧區(qū)

棧區(qū):由編譯器自動(dòng)分配釋放,存放函數(shù)的形參,局部變量
//不要返回局部變量的地址,棧區(qū)開(kāi)辟的數(shù)據(jù)由編譯器自動(dòng)釋放

04 堆區(qū)

堆區(qū):由程序員分配和釋放,若程序員不釋放,系統(tǒng)結(jié)束時(shí)由操作系統(tǒng)回收
//new可以創(chuàng)建堆區(qū)數(shù)據(jù),返回的是創(chuàng)建的堆區(qū)的地址,要用指針接收

05 new操作符

? int* arr = new int[10];//堆區(qū)開(kāi)辟數(shù)組

delete[] arr;//釋放數(shù)組

2 引用

06 引用的基本使用

作用:給變量起別名
語(yǔ)法:數(shù)據(jù)類(lèi)型 &別名=原名;

07 引用注意事項(xiàng)

引用必須初始化
引用初始化后不可以改變

int a = 10;//int& b;//err,引用必須初始化int& b = a;int c = 20;b = c;//這是賦值操作,不是更改引用,把b的值賦值成c的值20cout << a << b << c << endl;//20 20 20

08 引用做函數(shù)參數(shù)

引用傳遞讓形參修飾實(shí)參,簡(jiǎn)化指針修改實(shí)參?

通過(guò)引用參數(shù)產(chǎn)生的效果同按地址傳遞是一樣的,引用的語(yǔ)法更清楚簡(jiǎn)單

//引用傳遞 void mySwap(int &a,int &b) {int temp = a;a = b;b = temp; }int main() {int a = 1;int b = 2;cout << "a=" << a << endl;//1cout << "b=" << b << endl;//2mySwap(a, b);cout << "swap a=" << a << endl;//2cout << "swap b=" << b << endl;//1system("pause");return 0; }

09 引用做函數(shù)返回值

作用:引用是可以作為函數(shù)的返回值存在的

注意:不要返回局部變量引用

用法:函數(shù)返回值是引用時(shí),函數(shù)調(diào)用可以作為左值

//返回局部變量引用,非法操作 int& test01() {int a = 10;//局部變量存放在棧區(qū)return a; }//返回靜態(tài)變量引用,可以執(zhí)行 int& test02() {static int a = 10;//靜態(tài)變量,存放在全局區(qū),系統(tǒng)釋放return a; }int main() {//1.不要返回局部變量的引用int& ref = test01();cout << ref << endl;//第一次正確,因?yàn)榫幾g器做了保留//cout << ref << endl;//第二次錯(cuò)誤,因?yàn)閍的內(nèi)存已經(jīng)釋放int& ref2 = test02();cout << ref2 << endl;//10cout << ref2 << endl;//10cout << ref2 << endl;//10//2.如果函數(shù)的返回值是引用,這個(gè)函數(shù)的調(diào)用可以作為左值進(jìn)行賦值操作test02() = 1000;cout << ref2 << endl;//1000cout << ref2 << endl;//1000system("pause");return 0; }

10 引用的本質(zhì)

引用的本質(zhì)在C++內(nèi)部實(shí)現(xiàn)是一個(gè)指針常量

指針的指向是不可以修改指針指向的值是可以改動(dòng)

11 常量引用

用來(lái)修飾形參,防止誤操作

(在函數(shù)形參列表中,可以加const修飾形參,防止形參改變實(shí)參)

void showValue(const int& val)//函數(shù)中利用常量引用防止誤操作修改實(shí)參 {cout << val; } int main() {//常量引用:用來(lái)修飾形參,防止誤操作int a = 10;//int& ref = 10;//err,引用必須引一塊合法的內(nèi)存空間const int& ref = 10;//編譯器幫修改為int temp=10;int &ref=temp;//ref = 20;//加入const之后,變?yōu)橹蛔x,不可修改int a = 100;showValue(a);system("pause");return 0; }

3 函數(shù)提高

12函數(shù)默認(rèn)參數(shù)

語(yǔ)法:返回值類(lèi)型 函數(shù)名(形參=默認(rèn)值){ }

  • C++中函數(shù)的形參列表中的形參是可以有默認(rèn)值的
  • 如果有傳入數(shù)據(jù),就用傳入的數(shù)據(jù),如果沒(méi)有就用默認(rèn)值
  • 如果某個(gè)位置已經(jīng)有了默認(rèn)參數(shù),那么這個(gè)位置之后,從左到右都必須有默認(rèn)值
  • 聲明和實(shí)現(xiàn)只能有一個(gè)有默認(rèn)參數(shù);如果函數(shù)聲明有默認(rèn)參數(shù),函數(shù)實(shí)現(xiàn)就不能有默認(rèn)參數(shù)

13 函數(shù)占位參數(shù)

C++中函數(shù)形參列表里可以有占位參數(shù),用來(lái)占位,調(diào)用函數(shù)時(shí)必須填補(bǔ)該位置

語(yǔ)法:返回值類(lèi)型 函數(shù)名(數(shù)據(jù)類(lèi)型){}
?? ?//占位參數(shù)還可以有默認(rèn)參數(shù) (int=10),有默認(rèn)值時(shí),調(diào)用時(shí)可以不用傳值

14 函數(shù)重載

函數(shù)名可以相同,提高復(fù)用性

滿(mǎn)足條件:

  • 同一個(gè)作用域;
  • 函數(shù)名稱(chēng)相同;
  • 函數(shù)參數(shù)類(lèi)型不同或者個(gè)數(shù)不同或者順序不同
  • 函數(shù)的返回值不可以作為函數(shù)重載的條件

    注意事項(xiàng):

  • 引用可以作為函數(shù)重載條件,const int &a和int &a(const可以作為引用重載條件)
  • 函數(shù)重載碰到默認(rèn)參數(shù),容易出現(xiàn)二義性,盡量避免
  • 4 類(lèi)和對(duì)象

    面向?qū)ο笕筇匦?#xff1a;封裝、繼承、多態(tài)
    萬(wàn)物是對(duì)象,有屬性和行為

    具有相同性質(zhì)的對(duì)象,可以抽象為類(lèi)

    封裝

    16 封裝的意義 屬性和行為作為整體

    //設(shè)計(jì)一個(gè)圓類(lèi),求周長(zhǎng)

    const double PI = 3.14;class Circle {//訪(fǎng)問(wèn)權(quán)限:公共權(quán)限 public ://屬性int m_r;//半徑//行為:獲取圓的周長(zhǎng)double calculateZC(){return 2 * PI * m_r;} };//實(shí)例化(通過(guò)一個(gè)類(lèi),創(chuàng)建一個(gè)對(duì)象的過(guò)程)Circle c1;//通過(guò)圓類(lèi),創(chuàng)建具體的圓(對(duì)象)c1.m_r = 10;//給圓的對(duì)象的屬性賦值cout << "圓的周長(zhǎng)為:" << c1.calculateZC() << endl;

    實(shí)例化:通過(guò)一個(gè)類(lèi),創(chuàng)建一個(gè)對(duì)象的過(guò)程

    類(lèi)中的屬性和行為,統(tǒng)稱(chēng)為成員

    • 屬性 ?成員屬性 成員變量
    • 行為 成員函數(shù) 成員方法

    類(lèi)在設(shè)計(jì)時(shí),可以把屬性和行為放在不同的權(quán)限下,加以控制

    18?三種訪(fǎng)問(wèn)權(quán)限
    //公共權(quán)限 public? ? ? ? ? 成員類(lèi)內(nèi)可以訪(fǎng)問(wèn),類(lèi)外可以訪(fǎng)問(wèn)
    //保護(hù)權(quán)限 protected? ? 類(lèi)內(nèi)可以訪(fǎng)問(wèn),類(lèi)外不可以訪(fǎng)問(wèn)? ? ? ? ? ? 兒子可以訪(fǎng)問(wèn)父親中的保護(hù)內(nèi)容
    //私有權(quán)限 private? ? ? ? 類(lèi)內(nèi)可以訪(fǎng)問(wèn),類(lèi)外不可以訪(fǎng)問(wèn)? ? ? ? ? ? 兒子不可以訪(fǎng)問(wèn)父親中的私有內(nèi)容

    19 struct和class的區(qū)別:

    默認(rèn)的訪(fǎng)問(wèn)權(quán)限不同?
    struct默認(rèn)權(quán)限是? 公共? public
    class默認(rèn)權(quán)限是? ?私有? private

    20 成員屬性設(shè)置為私有的優(yōu)點(diǎn)

  • 可以自己控制讀寫(xiě)權(quán)限
  • 對(duì)于寫(xiě)權(quán)限,可以檢測(cè)數(shù)據(jù)的有效性
  • //設(shè)計(jì)立方體類(lèi)

    //創(chuàng)建立方體類(lèi) class Cube { public:void setL(int l){m_L = l;}void setW(int w){m_W = w;}void setH(int h){m_H = h;}int getL(){return m_L ;}int getW(){return m_W;}int getH(){return m_H;}int calculateS(){return 2 * m_L * m_W + 2 * m_H * m_W + 2 * m_L * m_H;}int calculateV(){return m_L * m_W * m_H;}//利用局部函數(shù)判斷是否相等bool isSamebyclass(Cube& c){if (getL() == c.getL() && getW() == c.getW() && getH() == c.getH())return true;elsereturn false;} private:int m_L;int m_W;int m_H; };//利用全局函數(shù)判斷兩個(gè)立方體是否相等 bool isSame(Cube& c1, Cube& c2) {if (c1.getL() == c2.getL() && c1.getW() == c2.getW() && c1.getH() == c2.getH())return true;elsereturn false; }int main() {Cube c1;c1.setL(10);c1.setW(10);c1.setH(10);cout<<"面積為"<<c1.calculateS()<<endl;cout << "體積為" << c1.calculateV() << endl;Cube c2;c2.setL(11);c2.setW(10);c2.setH(10);cout << "面積為" << c2.calculateS() << endl;cout << "體積為" << c2.calculateV() << endl;//利用全局函數(shù)判斷bool ret=isSame(c1,c2);if (ret)cout << "相等" << endl;elsecout << "不相等" <<endl;//利用局部函數(shù)判斷bool ret1 = c1.isSamebyclass(c2);if (ret1)cout << "相等" << endl;elsecout << "不相等" << endl;system("pause");return 0; }

    //判斷點(diǎn)和圓的關(guān)系?

    在類(lèi)中可以讓另一個(gè)類(lèi) 作為本類(lèi)中的成員

    可以把一個(gè)類(lèi)拆在不同文件中 .h聲明 .cpp實(shí)現(xiàn)

    對(duì)象特性:對(duì)象的初始化和清理

    每個(gè)對(duì)象也會(huì)有初識(shí)設(shè)置以及對(duì)象銷(xiāo)毀前的清理數(shù)據(jù)的設(shè)置

    23 構(gòu)造函數(shù)和析構(gòu)函數(shù)

    編譯器自動(dòng)調(diào)用,完成對(duì)象初始化和清理工作

    • 構(gòu)造函數(shù):創(chuàng)建對(duì)象時(shí)對(duì)象的成員屬性賦值
    • 析構(gòu)函數(shù):對(duì)象銷(xiāo)毀前,清理工作

    構(gòu)造函數(shù):類(lèi)名(){}

  • 沒(méi)有返回值,不用寫(xiě)void
  • 函數(shù)名與類(lèi)名相同
  • 構(gòu)造函數(shù)可以有參數(shù),可以發(fā)生重載
  • 創(chuàng)建對(duì)象的時(shí)候,構(gòu)造函數(shù)會(huì)自動(dòng)調(diào)用,而且只調(diào)用一次
  • 析構(gòu)函數(shù):~類(lèi)名(){}

  • 沒(méi)有返回值,不用寫(xiě)void
  • 函數(shù)名與類(lèi)名相同
  • 構(gòu)造函數(shù)不可以有參數(shù),不可以發(fā)生重載
  • 創(chuàng)建對(duì)象的時(shí)候,構(gòu)造函數(shù)會(huì)自動(dòng)調(diào)用,而且只調(diào)用一次?
  • 24 構(gòu)造函數(shù)的分類(lèi)和調(diào)用

    構(gòu)造函數(shù)分類(lèi):
    按照參數(shù):有參構(gòu)造和無(wú)參構(gòu)造(默認(rèn)構(gòu)造)
    按照類(lèi)型:普通構(gòu)造和拷貝構(gòu)造

    調(diào)用方式:
    1.括號(hào)法2.顯示法3.隱式轉(zhuǎn)換法

    class Person { public://無(wú)參構(gòu)造Person(){cout << "Person的無(wú)參(默認(rèn))構(gòu)造函數(shù)調(diào)用" << endl;}//有參構(gòu)造Person(int a){age = a;cout << "Person的有參構(gòu)造函數(shù)調(diào)用" << endl;}//拷貝構(gòu)造函數(shù)Person(const Person &p)//const+引用方式傳入{//將傳入的人身上的所有屬性,拷貝到當(dāng)前對(duì)象身上age = p.age;cout << "Person的拷貝構(gòu)造函數(shù)調(diào)用" << endl;}~Person(){cout << "Person的析構(gòu)函數(shù)調(diào)用" << endl;}int age; };void test01() {//1.括號(hào)法Person p;//默認(rèn)構(gòu)造函數(shù)的調(diào)用,調(diào)用默認(rèn)構(gòu)造函數(shù)的時(shí)候,不要加()Person p1(10);Person p2(p1);//拷貝構(gòu)造函數(shù)調(diào)用cout << "p2的年齡為" << p1.age << endl;cout << "p2的年齡為" << p2.age << endl;//注意:調(diào)用默認(rèn)構(gòu)造函數(shù)的時(shí)候,不要加()//Person p1();//err//編譯器會(huì)認(rèn)為是一個(gè)函數(shù)的聲明,不會(huì)認(rèn)為在創(chuàng)建對(duì)象2.顯示法Person p1;Person p2 = Person(10);Person p3 = Person(p2);//Person(10);//匿名對(duì)象,特點(diǎn):當(dāng)前行執(zhí)行結(jié)束后,系統(tǒng)會(huì)立即回收掉匿名對(duì)象注意:不要利用拷貝構(gòu)造函數(shù) 初始化匿名對(duì)象Person(p3);編譯器會(huì)認(rèn)為在對(duì)象聲明==Person p3;3.隱式轉(zhuǎn)換法Person p4 = 10;//相當(dāng)于 Person p4=Person(10);Person p5 = p4; }int main() {test01();system("pause");return 0; }

    ?25 拷貝構(gòu)造函數(shù)調(diào)用時(shí)機(jī)

    拷貝構(gòu)造函數(shù)調(diào)用時(shí)機(jī)三種情況:

  • 使用一個(gè)已經(jīng)創(chuàng)建完畢的對(duì)象來(lái)初始化一個(gè)對(duì)象
  • 值傳遞的方式給函數(shù)參數(shù)傳值
  • 以值方式返回局部對(duì)象
  • class Person { public:Person(){cout << "默認(rèn)構(gòu)造函數(shù)的調(diào)用" << endl;}Person(int age){m_Age = age;cout << "有參構(gòu)造函數(shù)的調(diào)用" << endl;}Person(const Person &p){m_Age = p.m_Age;cout << "拷貝構(gòu)造函數(shù)的調(diào)用" << endl;}~Person(){cout << "析構(gòu)函數(shù)的調(diào)用" << endl;}int m_Age; };//1.使用一個(gè)已經(jīng)創(chuàng)建完畢的對(duì)象來(lái)初始化一個(gè)對(duì)象void test01() {Person p1(20);Person p2(p1);cout << "p2的年齡為:" << p2.m_Age << endl; }//2.值傳遞的方式給函數(shù)參數(shù)傳值void doWork(Person p) {} void test02() {Person p;doWork(p); } //3.以值方式返回局部對(duì)象Person doWork2() {Person p1;return p1; } void test03() {Person p = doWork2(); } int main() {//test01();//test02();test03();system("pause");return 0; }

    26 構(gòu)造函數(shù)調(diào)用規(guī)則

    調(diào)用規(guī)則:

    如果我們寫(xiě)了有參構(gòu)造函數(shù),編譯器就不再提供默認(rèn)構(gòu)造,依然提供拷貝構(gòu)造
    如果我們寫(xiě)了拷貝構(gòu)造函數(shù),編譯器就不再提供其他普通構(gòu)造函數(shù)?

    27 深拷貝和淺拷貝

    淺拷貝:簡(jiǎn)單的復(fù)制拷貝操作
    淺拷貝帶來(lái)的問(wèn)題就是堆區(qū)的內(nèi)存重復(fù)釋放

    深拷貝:在堆區(qū)重新申請(qǐng)空間,進(jìn)行拷貝操作

    //如果屬性有在堆區(qū)開(kāi)辟的,一定要自己提供拷貝構(gòu)造函數(shù),防止淺拷貝帶來(lái)的問(wèn)題

    class Person { public:Person(){cout << "Person的默認(rèn)構(gòu)造函數(shù)調(diào)用" << endl;}Person(int age,int height){m_Age = age;m_Height=new int(height);cout << "Person的有參構(gòu)造函數(shù)調(diào)用" << endl;}//自己實(shí)現(xiàn)拷貝構(gòu)造函數(shù),解決淺拷貝帶來(lái)的問(wèn)題Person(const Person& p){cout << "Person拷貝構(gòu)造函數(shù)調(diào)用" << endl;m_Age = p.m_Age;//m_Height = p.m_Height;編譯器默認(rèn)實(shí)現(xiàn)的代碼,淺拷貝//深拷貝操作m_Height = new int(*p.m_Height);}~Person(){//析構(gòu)代碼,將堆區(qū)開(kāi)辟數(shù)據(jù)做釋放操作if (m_Height != NULL){delete m_Height;m_Height = NULL;}cout << "Person的析構(gòu)函數(shù)調(diào)用" << endl;}int m_Age;//年齡int* m_Height; };void test01() {Person p1(18,160);cout << "p1的年齡為:" << p1.m_Age <<"身高為:"<<*p1.m_Height<< endl;Person p2(p1);cout << "p2的年齡為:" << p2.m_Age << "身高為:" << *p2.m_Height << endl;} int main() {test01();system("pause");return 0; }

    28 初始化列表

    //初始化列表Person(int a,int b,int c) :m_A(a), m_B(b), m_C(c){} //屬性賦初值 Person p(31,20,10);

    29 類(lèi)對(duì)象作為類(lèi)成員

    類(lèi)中的成員可以是另一個(gè)類(lèi)的對(duì)象,我們稱(chēng)該成員為對(duì)象成員

    • 當(dāng)其他類(lèi)對(duì)象作為本類(lèi)成員,構(gòu)造時(shí)候先構(gòu)造類(lèi)對(duì)象,再構(gòu)造自身
    • 當(dāng)其他類(lèi)對(duì)象作為本類(lèi)成員,析構(gòu)時(shí)候先析構(gòu)自身,再析構(gòu)類(lèi)對(duì)象

    構(gòu)造順序與析構(gòu)順序相反

    class Phone { public:Phone(string pName){m_PName = pName;cout << "phone的構(gòu)造函數(shù)調(diào)用" << endl;}~Phone(){cout << "phone的析構(gòu)函數(shù)調(diào)用" << endl;}string m_PName; }; class Person { public:Person(string name, string pName):m_Name(name),m_phone(pName){cout << "person的構(gòu)造函數(shù)調(diào)用" << endl;}~Person(){cout << "person的析構(gòu)函數(shù)調(diào)用" << endl;}string m_Name;Phone m_phone; };

    30 靜態(tài)成員

    靜態(tài)成員變量:

    • 所有對(duì)象共享同一份數(shù)據(jù)
    • 在編譯階段分配內(nèi)存(程序運(yùn)行前-全局區(qū))
    • 類(lèi)內(nèi)聲明,類(lèi)外初始化
    class Person { public:static int m_A;//類(lèi)內(nèi)聲明};int Person::m_A = 100;//類(lèi)外初始化void test01() {Person p;cout << p.m_A << endl;//100Person p2;p2.m_A = 200;//所有對(duì)象共享同一份數(shù)據(jù)cout << p.m_A << endl;//200 }

    靜態(tài)成員變量,不屬于某個(gè)對(duì)象上,所有對(duì)象都共享同一份數(shù)據(jù)?
    有兩種訪(fǎng)問(wèn)方式:

  • 通過(guò)對(duì)象進(jìn)行訪(fǎng)問(wèn)
  • 通過(guò)類(lèi)名進(jìn)行訪(fǎng)問(wèn)
  • Person p; cout<<p.m_A<<endl;cout<<Person::m_A<<endl;

    靜態(tài)成員變量有訪(fǎng)問(wèn)權(quán)限,類(lèi)外訪(fǎng)問(wèn)不到私有靜態(tài)成員變量

    31 靜態(tài)成員函數(shù)

    • 所有對(duì)象共享同一個(gè)函數(shù)
    • 靜態(tài)成員函數(shù)只能訪(fǎng)問(wèn)靜態(tài)成員變量

    //兩種訪(fǎng)問(wèn)方式:通過(guò)對(duì)象,通過(guò)類(lèi)名
    //靜態(tài)成員函數(shù)也是有訪(fǎng)問(wèn)權(quán)限的,類(lèi)外訪(fǎng)問(wèn)不到私有的靜態(tài)成員函數(shù)

    class Person { public://靜態(tài)成員函數(shù)static void func(){m_A = 100;//靜態(tài)成員函數(shù)可以訪(fǎng)問(wèn)靜態(tài)成員變量,共享的//m_B = 200;//靜態(tài)成員函數(shù)不可以訪(fǎng)問(wèn)非靜態(tài)成員變量,因?yàn)闊o(wú)法區(qū)分到底是哪個(gè)對(duì)象的m_Bcout << "ststic void func()的調(diào)用" << endl;}static int m_A;//類(lèi)內(nèi)聲明,類(lèi)外初始化int m_B;//非靜態(tài)成員變量 };int Person::m_A=0;//類(lèi)外初始化void test01() {//靜態(tài)成員函數(shù)有兩種訪(fǎng)問(wèn)方式//通過(guò)對(duì)象訪(fǎng)問(wèn)Person p;p.func();//通過(guò)類(lèi)名訪(fǎng)問(wèn),因?yàn)椴粚儆谀骋粋€(gè)對(duì)象上,不創(chuàng)建對(duì)象也可以訪(fǎng)問(wèn)Person::func(); }

    對(duì)象特性:C++對(duì)象模型和this指針

    32 成員變量和成員函數(shù)分開(kāi)存儲(chǔ)

    只有非靜態(tài)成員變量 屬于對(duì)象上的數(shù)據(jù)

    ??空對(duì)象占用內(nèi)存空間為:1
    ?? ?//C++編譯器會(huì)給每個(gè)空對(duì)象也分配一個(gè)字節(jié)空間,是為了區(qū)分空對(duì)象占內(nèi)存的位置
    ?? ?//每個(gè)空對(duì)象也應(yīng)該有一個(gè)獨(dú)一無(wú)二的內(nèi)存地址

    class Person {int m_A;//非靜態(tài)成員變量 屬于對(duì)象上的數(shù)據(jù)static int m_B;//靜態(tài)成員變量 不屬于類(lèi)的對(duì)象上void func(){}//非靜態(tài)成員函數(shù) 不屬于類(lèi)的對(duì)象上static void func2() {}//靜態(tài)成員函數(shù) 不屬于類(lèi)的對(duì)象上 }; int Person::m_B=0;void test02() {Person p;cout << "sizeofp=" << sizeof(p) << endl;//4 }

    33 this指針

    this指針:指向被調(diào)用的成員函數(shù)所屬的對(duì)象
    this指針是隱含每一個(gè)非靜態(tài)成員函數(shù)內(nèi)的一種指針
    this指針不需要定義,直接使用
    用途:
    //當(dāng)形參和成員變量同名時(shí),可用this指針來(lái)區(qū)分
    //在類(lèi)的非靜態(tài)成員函數(shù)中返回對(duì)象本身,可使用return *this

    class Person { public:Person(int age){//this指針指向被調(diào)用的成員函數(shù)所屬的對(duì)象this->age = age;}//如果用Person返回就是用值的方式返回,會(huì)用到拷貝構(gòu)造函數(shù),Person返回的和自身是不一樣的數(shù)據(jù)//用引用方式返回,不會(huì)創(chuàng)建新的對(duì)象,會(huì)一直返回P2本體Person& PersonAddAge(Person& p)//Person& 不返回引用就會(huì)通過(guò)拷貝構(gòu)造創(chuàng)建新對(duì)象,就不是原來(lái)的對(duì)象了{(lán)this->age += p.age;//this是指向p2的指針,*this指向的就是p2這個(gè)對(duì)象的本體return *this;}int age; }; void test02() {Person p1(10);Person p2(10);p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);//鏈?zhǔn)骄幊趟枷隿out << "p2的年齡為:" << p2.age << endl; } void test01() {Person p1(18);cout << "p1的年齡為:" << p1.age << endl; }test01();test02();

    34 空指針訪(fǎng)問(wèn)成員函數(shù)

    C++中允許空指針調(diào)用成員函數(shù),也要注意有沒(méi)有用到this指針
    //如果用到this指針,需要判斷保證代碼的健壯性

    35 const修飾成員函數(shù)

    常函數(shù)
    成員函數(shù)后加const稱(chēng)為常函數(shù)
    //常函數(shù)內(nèi)不可以修改成員屬性(指針指向的值不能修改)
    //成員屬性聲明時(shí)加關(guān)鍵字mutable后,在常函數(shù)中依然可以修改
    常對(duì)象
    聲明對(duì)象前加const稱(chēng)為常對(duì)象
    //常對(duì)象只能調(diào)用常函數(shù)

    友元

    36 全局函數(shù)做友元

    class Building {friend void goodgay(Building* builiding);//goodgay是Building好朋友,可以訪(fǎng)問(wèn)Builing中私有成員 public:Building(){m_SittingRoom = "客廳";m_BedRoom = "臥室";} public:string m_SittingRoom;private:string m_BedRoom;}; //全局函數(shù) void goodgay(Building *builiding) {cout << "全局函數(shù)正在訪(fǎng)問(wèn):" << builiding->m_BedRoom << endl;cout << "全局函數(shù)正在訪(fǎng)問(wèn):" << builiding->m_SittingRoom << endl; }

    37 友元類(lèi)

    friend class goodgay;//goodgay類(lèi)是本類(lèi)的好朋友,可以訪(fǎng)問(wèn)本類(lèi)中私有的成員

    38 成員函數(shù)做友元

    friend void Goodgay::visit01();//goodgay類(lèi)下的visit成員函數(shù)作為本類(lèi)的好朋友,可以訪(fǎng)問(wèn)私有成員

    C++運(yùn)算符重載

    運(yùn)算符重載:對(duì)已有運(yùn)算符重新進(jìn)行定義,賦予另一種功能,以適應(yīng)不同的數(shù)據(jù)類(lèi)型

    39 加號(hào)運(yùn)算符重載?

    作用:實(shí)現(xiàn)兩個(gè)自定義數(shù)據(jù)類(lèi)型相加的運(yùn)算
    //對(duì)于內(nèi)置的數(shù)據(jù)類(lèi)型表達(dá)式運(yùn)算符是不可能改變的
    //不要濫用運(yùn)算符重載

    class Person { public://1.成員函數(shù)重載加號(hào): Person p3=p1+p2;成員函數(shù)的本質(zhì)是 Person p3=p1.operator+(p2);/*Person operator+(Person& p){Person temp;temp.m_A = this->m_A + p.m_A;temp.m_B = this->m_B + p.m_B;return temp;}*/int m_A;int m_B;};//2.全局函數(shù)重載加號(hào): Person p3=p1+p2;全局函數(shù)的本質(zhì)是 Person p3= operator+(p1,p2); Person operator+(Person &p1,Person &p2) {Person temp;temp.m_A = p1.m_A + p2.m_A;temp.m_B = p1.m_B + p2.m_B;return temp; }//3.運(yùn)算符重載也可以發(fā)生函數(shù)重載 Person operator+(Person& p1, int num) {Person temp;temp.m_A = p1.m_A +num;temp.m_B = p1.m_B +num;return temp; } void test01() {Person p1;p1.m_A = 10;p1.m_B = 10;Person p2;p2.m_A = 10;p2.m_B = 10;Person p3 = p1 + p2;//運(yùn)算符重載也可以發(fā)生函數(shù)重載Person p4 = p1 + 100;cout << "p3.m_A=" << p3.m_A << endl;cout << "p3.m_B=" << p3.m_B << endl;cout << "p4.m_A=" << p4.m_A << endl;cout << "p4.m_B=" << p4.m_B << endl; }

    40 左移運(yùn)算符重載

    輸出左移運(yùn)算符配合友元可以實(shí)現(xiàn)輸出自定義數(shù)據(jù)類(lèi)型

    class Person {friend ostream& operator<<(ostream& cout, Person& p); public:Person(int a, int b){m_A = a;m_B = b;} private://不會(huì)利用成員函數(shù)重載左移運(yùn)算符<<,因?yàn)闊o(wú)法實(shí)現(xiàn)cout在左側(cè)int m_A;int m_B;};//只能利用全局函數(shù)重載左移運(yùn)算符 ostream& operator<<(ostream &cout,Person &p)//本質(zhì)是operator<<(cout,p) 簡(jiǎn)化cout<<p {cout << "m_A=" << p.m_A << endl;cout << "m_B=" << p.m_B << endl;return cout;//為了可以無(wú)限往后追加輸出 } void test01() {Person p(10, 10);cout << p <<"hello"<< endl;; }

    41 遞增運(yùn)算符重載

    通過(guò)重載遞增運(yùn)算符,實(shí)現(xiàn)自己的整形數(shù)據(jù)

    前置遞增返回參數(shù),后置遞增返回值??

    //++//自定義整形 class MyInteger {friend ostream& operator<<(ostream& cout, MyInteger myint); public:MyInteger(){m_Num = 0;}//重載++運(yùn)算符//1.重載前置++ MyInteger& operator++()//返回引用是為了一直對(duì)一個(gè)數(shù)據(jù)進(jìn)行遞增操作{//先進(jìn)行++運(yùn)算m_Num++;//再將自身返回return *this;}//2.重載后置++ //返回的是值,因?yàn)榉祷氐氖蔷植孔兞縈yInteger operator++(int)//int代表占位參數(shù),可以用于區(qū)分前置和后置遞增,編譯器會(huì)認(rèn)為這是后置遞增重載{//先記錄當(dāng)時(shí)結(jié)果MyInteger temp = *this;//后遞增m_Num++;//再返回之前記錄的結(jié)果return temp;} private:int m_Num; };//重載左移運(yùn)算符 ostream& operator<<(ostream& cout, MyInteger myint) {cout << myint.m_Num << endl;return cout; }void test01() {MyInteger myint;cout << ++(++myint) << endl; } void test02() {MyInteger myint;cout << myint++ << endl;cout << myint << endl; }test01();test02();

    42 賦值運(yùn)算符重載

    Person& operator=(Person& p){//編譯器提供的是淺拷貝//m_Age=p.m_Age;//應(yīng)該先判斷有屬性在堆區(qū),如果有先釋放干凈,然后再深拷貝if (m_Age != NULL){delete m_Age;m_Age = NULL;}m_Age=new int(*p.m_Age);//深拷貝return *this;}

    43 關(guān)系運(yùn)算符重載

    //重載==bool operator==(Person& p){if (this->m_Age == p.m_Age && this->m_Name == p.m_Name){return true;}else false;}//重載!=bool operator!=(Person& p){if (this->m_Age == p.m_Age && this->m_Name == p.m_Name){return false;}else true;}

    44 函數(shù)調(diào)用運(yùn)算符重載

    函數(shù)調(diào)用運(yùn)算符()也可以重載

    由于重載后使用的方式非常像函數(shù)的調(diào)用,因此稱(chēng)為仿函數(shù)

    仿函數(shù)沒(méi)有固定的寫(xiě)法,非常靈活

    //打印輸出 class MyPrint { public://重載函數(shù)調(diào)用運(yùn)算符void operator()(string test){cout << test << endl;} }; void test01() {MyPrint myPrint;myPrint("hello");//由于使用起來(lái)類(lèi)似于函數(shù)調(diào)用,稱(chēng)為仿函數(shù) } //仿函數(shù)非常靈活,沒(méi)有固定的寫(xiě)法 //加法類(lèi) class MyAdd { public:int operator()(int num1, int num2){return num1 + num2;} }; void test02() {MyAdd myadd;int ret = myadd(100, 200);cout << ret << endl;//匿名函數(shù)對(duì)象 //MyAdd()cout << MyAdd()(100, 200) << endl; } int main() {test01();test02();return 0; }

    繼承

    45 基本語(yǔ)法

    繼承的好處:減少重復(fù)代碼
    語(yǔ)法: class 子類(lèi):繼承方式 父類(lèi)

    ? ? ? ? ? ? class A : publib B
    ????????????A類(lèi),子類(lèi)也稱(chēng)為派生類(lèi)
    ????????????B類(lèi),父類(lèi)也稱(chēng)為基類(lèi)

    派生類(lèi)中的成員,包含兩大部分:一類(lèi)是從基類(lèi)繼承過(guò)來(lái)的,一類(lèi)是自己增加的成員

    從基類(lèi)繼承過(guò)來(lái)的表現(xiàn)其共性,而新增的成員體現(xiàn)其個(gè)性

    46 繼承方式

    ?繼承的三種方式:

    • 公共繼承
    • 保護(hù)繼承
    • 私有繼承

    47 繼承中的對(duì)象模型

    class Base { public:int a; protected:int b; private:int c;};class Son :public Base { public:int d;};void test01() {//父類(lèi)中所有靜態(tài)成員屬性都會(huì)被子類(lèi)繼承下去//父類(lèi)中私有成員屬性是被編譯器給隱藏了,因此是訪(fǎng)問(wèn)不到,但是確實(shí)被繼承下去了cout << "size of Son=" << sizeof(Son) << endl;//16 }

    利用開(kāi)發(fā)人員命令提示工具(Developer Command Prompt for VS 2019)查看對(duì)象模型
    //跳轉(zhuǎn)盤(pán)符 F:
    //跳轉(zhuǎn)文件路徑 cd 具體路徑下
    //查看命令 cl /d1 reportSingleClassLayout類(lèi)名 文件名
    ? ? ? ? ? ? ? ? F:\C++-code\0421繼承>cl /d1 reportSingleClassLayoutSon "129對(duì)象基本模型.cpp"?

    48 構(gòu)造和析構(gòu)順序

    子類(lèi)繼承父類(lèi)后,當(dāng)創(chuàng)建子類(lèi)對(duì)象,也會(huì)調(diào)用父類(lèi)的構(gòu)造函數(shù)
    繼承中的構(gòu)造和析構(gòu)的順序:
    先構(gòu)造父類(lèi),再構(gòu)造子類(lèi);析構(gòu)順序與構(gòu)造順序相反

    49 同名成員處理

    當(dāng)子類(lèi)與父類(lèi)出現(xiàn)同名的成員,如何通過(guò)子類(lèi)對(duì)象,訪(fǎng)問(wèn)到其中的同名數(shù)據(jù):
    1.訪(fǎng)問(wèn)子類(lèi)同名成員,直接訪(fǎng)問(wèn)即可
    2.訪(fǎng)問(wèn)父類(lèi)同名成員,需要加作用域

    Son s;cout << "Son的m_A=" << s.m_A << endl;cout << "Base的m_A=" << s.Base::m_A << endl;//如果通過(guò)子類(lèi)對(duì)象,訪(fǎng)問(wèn)到父類(lèi)中的同名成員,需要加作用域s.func();//直接調(diào)用的是子類(lèi)中的同名函數(shù)s.Base::func();//調(diào)用的是父類(lèi)的
    • 如果子類(lèi)中出現(xiàn)和父類(lèi)中同名的成員函數(shù),子類(lèi)的同名成員會(huì)隱藏掉父類(lèi)中所有同名成員函數(shù)(包括重載版本)
    • 如果想訪(fǎng)問(wèn)到父類(lèi)中被隱藏的同名成員函數(shù),需要加作用域?

    50 同名靜態(tài)成員處理

    ?同名靜態(tài)成員處理方式和非靜態(tài)處理方式一樣,只不過(guò)有兩種訪(fǎng)問(wèn)方式(通過(guò)對(duì)象和通過(guò)類(lèi)名

    class Base{public:static int m_A;static void func(){cout << "Base 的func的調(diào)用" << endl;}};int Base::m_A = 100;class Son :public Base{public:static int m_A;static void func(){cout << "Son 的func的調(diào)用" << endl;}};int Son::m_A = 200;void test01(){//通過(guò)對(duì)象訪(fǎng)問(wèn)Son s;cout << "Son的m_A=" << s.m_A << endl;cout << "Base的m_A=" << s.Base::m_A << endl;//通過(guò)類(lèi)名訪(fǎng)問(wèn)cout << Son::m_A << endl;cout << Base::m_A << endl;cout << Son::Base::m_A << endl;//第一個(gè)::代表通過(guò)類(lèi)名方式訪(fǎng)問(wèn),第二個(gè)::代表訪(fǎng)問(wèn)父類(lèi)作用域下的m_A}void test02(){//通過(guò)對(duì)象訪(fǎng)問(wèn)Son s;s.func();s.Base::func();//通過(guò)類(lèi)名訪(fǎng)問(wèn)Son::func();Son::Base::func();}

    51 多繼承語(yǔ)法

    C++允許一個(gè)類(lèi)繼承多個(gè)類(lèi)

    語(yǔ)法:class 子類(lèi):繼承方式 父類(lèi)1,繼承方式 父類(lèi)2
    //多繼承可能會(huì)引發(fā)父類(lèi)中有同名成員出現(xiàn),需要加作用域
    //開(kāi)發(fā)中不建議用多繼承

    //子類(lèi)繼承兩個(gè)父類(lèi)class Son :public Base1, public Base2 //父類(lèi)中出現(xiàn)同名成員時(shí),需要加作用域區(qū)分cout << s.Base1::m_A << endl;cout << s.Base2::m_A << endl;

    52 菱形繼承問(wèn)題以及解決方法

    菱形繼承、鉆石繼承

    • 兩個(gè)派生類(lèi)繼承同一個(gè)類(lèi)
    • 又有某個(gè)類(lèi)同時(shí)繼承兩個(gè)派生類(lèi)?

    多態(tài)

    53 多態(tài)的基本語(yǔ)法

    動(dòng)態(tài)多態(tài)滿(mǎn)足條件:

  • 要有繼承關(guān)系
  • 子類(lèi)重寫(xiě)父類(lèi)的虛函數(shù) ? //重寫(xiě):函數(shù)返回值類(lèi)型 函數(shù)名 參數(shù)列表 完全相同
  • 動(dòng)態(tài)多態(tài)使用:父類(lèi)的指針或引用 指向子類(lèi)對(duì)象?

    54 多態(tài)的原理剖析

    //示例:多態(tài)原理剖析

    //動(dòng)物類(lèi) class Animal { public:virtual void speak(){cout << "動(dòng)物在說(shuō)話(huà)" << endl;} };//貓類(lèi) class Cat :public Animal { public://虛函數(shù)void speak(){cout << "小貓?jiān)谡f(shuō)話(huà)" << endl;} };//狗類(lèi) class Dog :public Animal { public://虛函數(shù)void speak(){cout << "小狗在說(shuō)話(huà)" << endl;} }; void doSpeak(Animal &animal) {animal.speak(); }void test01() {Cat cat;doSpeak(cat);Dog dog;doSpeak(dog);}

    多態(tài)優(yōu)點(diǎn):代碼組織結(jié)構(gòu)清晰可讀性強(qiáng),利于前期和后期的擴(kuò)展及維護(hù)

    在真實(shí)的開(kāi)發(fā)中,提倡 開(kāi)閉原則
    開(kāi)閉原則:對(duì)擴(kuò)展進(jìn)行開(kāi)發(fā),對(duì)修改進(jìn)行關(guān)閉

    56 純虛函數(shù)和抽象函數(shù)

    當(dāng)類(lèi)中有了純虛函數(shù),這個(gè)類(lèi)就是抽象類(lèi)?

    ?//抽象類(lèi)無(wú)法實(shí)例化對(duì)象
    ?//子類(lèi)必須重寫(xiě)抽象類(lèi)中的純虛函數(shù),否則也屬于抽象類(lèi),無(wú)法實(shí)例化對(duì)象

    58 虛析構(gòu)和純虛析構(gòu)

    父類(lèi)指針在析構(gòu)的時(shí)候,不會(huì)調(diào)用子類(lèi)中析構(gòu)函數(shù),導(dǎo)致子類(lèi)中如果有堆區(qū)屬性,出現(xiàn)內(nèi)存泄漏?

    虛析構(gòu)和純虛析構(gòu)的共性

    • 可以解決父類(lèi)指針釋放子類(lèi)對(duì)象時(shí)不干凈的問(wèn)題
    • 都需要有具體的函數(shù)實(shí)現(xiàn)

    虛析構(gòu)和純虛析構(gòu)的區(qū)別

    • 如果是純虛析構(gòu),該類(lèi)屬于抽象類(lèi),無(wú)法實(shí)例化對(duì)象

    虛析構(gòu):virtual ~類(lèi)名(){}

    純虛析構(gòu)virtual ~類(lèi)名() = 0;//聲明
    ? ? ? ? ? ? ? ? ? 類(lèi)名 :: ~類(lèi)名() {}? //具體實(shí)現(xiàn)

    總結(jié):

  • 虛析構(gòu)和純虛析構(gòu)就是用來(lái)解決通過(guò)父類(lèi)指針釋放子類(lèi)對(duì)象
  • 如果子類(lèi)中沒(méi)有堆區(qū)數(shù)據(jù),可以不寫(xiě)虛析構(gòu)或純虛析構(gòu)
  • 擁有純虛析構(gòu)函數(shù)的類(lèi)也屬于抽象類(lèi)
  • 5 文件操作

    文本文件

    143 寫(xiě)文件

    寫(xiě)文件步驟:

  • 包含頭文件#include<fstream>
  • 創(chuàng)建流對(duì)象 ofstream ofs;
  • 打開(kāi)文件 ofs.open("文件路徑",打開(kāi)方式);
  • 寫(xiě)數(shù)據(jù) ofs << "寫(xiě)入的數(shù)據(jù)";
  • 關(guān)閉文件 ofs.close();
  • ofstream ofs; ofs.open("text.txt", ios::out); ofs << "姓名:張三" << endl; ofs.close();

    144 讀文件

    ifstream ifs; ifs.open("text.txt", ios::in); if (!ifs.is_open()) {cout << "文件打開(kāi)失敗" << endl;return; } //讀文件的四種方式 //1 char buf[1024] = { 0 }; while (ifs >> buf) {cout << buf << endl; }//2 char buf[1024] = { 0 }; while (ifs.getline(buf, sizeof(buf))) {cout << buf << endl; }//3 string buf; while (getline(ifs, buf)) {cout << buf << endl; }*//4不推薦 char c; while ((c = ifs.get()) != EOF) {cout << c; }

    二進(jìn)制文件

    以二進(jìn)制的方式對(duì)文件進(jìn)行讀寫(xiě)操作

    打開(kāi)方式要指定為ios::binary

    145 寫(xiě)文件

    ofstream ofs; ofs.open("Person.txt", ios::out | ios::binary); Person p = { "張三",18 }; ofs.write((const char *)&p,sizeof(Person)); ofs.close();

    146 讀文件

    ifstream ifs;ifs.open("person.txt", ios::in | ios::binary);if (!ifs.is_open()){cout << "文件打開(kāi)失敗" << endl;return;}Person p;ifs.read((char*)&p, sizeof(Person));cout << p.m_name << p.m_age << endl;ifs.close();

    總結(jié)

    以上是生活随笔為你收集整理的笔记 黑马程序员C++教程从0到1入门编程——核心编程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。