熬夜爆肝!C++核心進階知識點匯總整理【萬字干貨預警 建議收藏】(上)
前言
前段時間有粉絲問我,大一結束c++剛學完,不知道自己目前學得怎么樣?要掌握的知識點有沒有都弄懂了?是否基礎入門了?
前幾天已經整理過C++基礎入門知識點,沒看過的可以看看喔!熬夜爆肝!C++基礎入門大合集【萬字干貨預警 建議】
今天繼續(xù)整理C++進階篇知識點,一起來看看吧~
C++核心編程
主要針對C++面向對象編程技術做詳細講解,探討C++的核心和精髓。
1 內存分區(qū)模型
C++程序在執(zhí)行時,將內存大方向劃分為4個區(qū)域
代碼區(qū):存放函數體的二進制代碼,由操作系統(tǒng)進行管理的
全局區(qū):存放全局變量和靜態(tài)變量以及常量
棧區(qū):由編譯器自動分配釋放, 存放函數的參數值,局部變量等
堆區(qū):由程序員分配和釋放,若程序員不釋放,程序結束時由操作系統(tǒng)回收
內存四區(qū)意義:
不同區(qū)域存放的數據,賦予不同的生命周期, 給我們更大的靈活編程
1.1 程序運行前
在程序編譯后,生成了exe可執(zhí)行程序,未執(zhí)行該程序前分為兩個區(qū)域
代碼區(qū):
存放 CPU 執(zhí)行的機器指令
代碼區(qū)是共享的,共享的目的是對于頻繁被執(zhí)行的程序,只需要在內存中有一份代碼即可
代碼區(qū)是只讀的,使其只讀的原因是防止程序意外地修改了它的指令
全局區(qū):
全局變量和靜態(tài)變量存放在此.
全局區(qū)還包含了常量區(qū), 字符串常量和其他常量也存放在此.
該區(qū)域的數據在程序結束后由操作系統(tǒng)釋放.
示例:
//全局變量 int g_a = 10; int g_b = 10; //全局常量 const int c_g_a = 10; const int c_g_b = 10; int main() { //局部變量 int a = 10; int b = 10; //打印地址 cout << "局部變量a地址為: " << (int)&a << endl; cout << "局部變量b地址為: " << (int)&b << endl; cout << "全局變量g_a地址為: " << (int)&g_a << endl; cout << "全局變量g_b地址為: " << (int)&g_b << endl; //靜態(tài)變量 static int s_a = 10; static int s_b = 10; cout << "靜態(tài)變量s_a地址為: " << (int)&s_a << endl; cout << "靜態(tài)變量s_b地址為: " << (int)&s_b << endl; cout << "字符串常量地址為: " << (int)&"hello world" << endl; cout << "字符串常量地址為: " << (int)&"hello world1" << endl; cout << "全局常量c_g_a地址為: " << (int)&c_g_a << endl; cout << "全局常量c_g_b地址為: " << (int)&c_g_b << endl; const int c_l_a = 10; const int c_l_b = 10; cout << "局部常量c_l_a地址為: " << (int)&c_l_a << endl; cout << "局部常量c_l_b地址為: " << (int)&c_l_b << endl; system("pause"); return 0; }
打印結果:
C++中在程序運行前分為全局區(qū)和代碼區(qū)
代碼區(qū)特點是共享和只讀
全局區(qū)中存放全局變量、靜態(tài)變量、常量
常量區(qū)中存放 const修飾的全局常量 和 字符串常量
1.2 程序運行后
棧區(qū):
由編譯器自動分配釋放, 存放函數的參數值,局部變量等
注意事項:不要返回局部變量的地址,棧區(qū)開辟的數據由編譯器自動釋放
示例:
int * func() { int a = 10; return &a; } int main() { int *p = func(); cout << *p << endl; cout << *p << endl; system("pause"); return 0; }
堆區(qū):
由程序員分配釋放,若程序員不釋放,程序結束時由操作系統(tǒng)回收
在C++中主要利用new在堆區(qū)開辟內存
示例:
int* func() { int* a = new int(10); return a; } int main() { int *p = func(); cout << *p << endl; cout << *p << endl; system("pause"); return 0; }
總結:
堆區(qū)數據由程序員管理開辟和釋放
堆區(qū)數據利用new關鍵字進行開辟內存
1.3 new操作符
C++中利用new操作符在堆區(qū)開辟數據
堆區(qū)開辟的數據,由程序員手動開辟,手動釋放,釋放利用操作符 delete
語法:new 數據類型
利用new創(chuàng)建的數據,會返回該數據對應的類型的指針
示例1: 基本語法
int* func() { int* a = new int(10); return a; } int main() { int *p = func(); cout << *p << endl; cout << *p << endl; //利用delete釋放堆區(qū)數據 delete p; //cout << *p << endl; //報錯,釋放的空間不可訪問 system("pause"); return 0; }
示例2:開辟數組
//堆區(qū)開辟數組 int main() { int* arr = new int[10]; for (int i = 0; i < 10; i++) { arr[i] = i + 100; } for (int i = 0; i < 10; i++) { cout << arr[i] << endl; } //釋放數組 delete 后加 [] delete[] arr; system("pause"); return 0; }
2 引用
2.1 引用的基本使用
**作用: **給變量起別名
語法: 數據類型 &別名 = 原名
示例:
int main() { int a = 10; int &b = a; cout << "a = " << a << endl; cout << "b = " << b << endl; b = 100; cout << "a = " << a << endl; cout << "b = " << b << endl; system("pause"); return 0; }
2.2 引用注意事項
引用必須初始化
引用在初始化后,不可以改變
示例:
int main() { int a = 10; int b = 20; //int &c; //錯誤,引用必須初始化 int &c = a; //一旦初始化后,就不可以更改 c = b; //這是賦值操作,不是更改引用 cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl; system("pause"); return 0;
}
2.3 引用做函數參數
**作用:**函數傳參時,可以利用引用的技術讓形參修飾實參
**優(yōu)點:**可以簡化指針修改實參
示例:
//1. 值傳遞 void mySwap01(int a, int b) { int temp = a; a = b; b = temp; } //2. 地址傳遞 void mySwap02(int* a, int* b) { int temp = *a; *a = *b; *b = temp; } //3. 引用傳遞 void mySwap03(int& a, int& b) { int temp = a; a = b; b = temp; } int main() { int a = 10; int b = 20; mySwap01(a, b); cout << "a:" << a << " b:" << b << endl; mySwap02(&a, &b); cout << "a:" << a << " b:" << b << endl; mySwap03(a, b); cout << "a:" << a << " b:" << b << endl; system("pause"); return 0; }
2.4 引用做函數返回值
引用是可以作為函數的返回值存在的,不要返回局部變量引用。
用法:函數調用作為左值
//返回局部變量引用 int& test01() { int a = 10; //局部變量 return a; } //返回靜態(tài)變量引用 int& test02() { static int a = 20; return a; } int main() { //不能返回局部變量的引用 int& ref = test01(); cout << "ref = " << ref << endl; cout << "ref = " << ref << endl; //如果函數做左值,那么必須返回引用 int& ref2 = test02(); cout << "ref2 = " << ref2 << endl; cout << "ref2 = " << ref2 << endl; test02() = 1000; cout << "ref2 = " << ref2 << endl; cout << "ref2 = " << ref2 << endl; system("pause"); return 0; }
2.5 引用的本質
本質:引用的本質在c++內部實現(xiàn)是一個指針常量.
C++推薦用引用技術,因為語法方便,引用本質是指針常量,但是所有的指針操作編譯器都幫我們做了
//發(fā)現(xiàn)是引用,轉換為 int* const ref = &a; void func(int& ref){ ref = 100; // ref是引用,轉換為*ref = 100 } int main(){ int a = 10; //自動轉換為 int* const ref = &a; 指針常量是指針指向不可改,也說明為什么引用不可更改 int& ref = a; ref = 20; //內部發(fā)現(xiàn)ref是引用,自動幫我們轉換為: *ref = 20; cout << "a:" << a << endl; cout << "ref:" << ref << endl; func(a); return 0; }
2.6 常量引用
常量引用主要用來修飾形參,防止誤操作
在函數形參列表中,可以加const修飾形參,防止形參改變實參
//引用使用的場景,通常用來修飾形參 void showValue(const int& v) { //v += 10; cout << v << endl; } int main() { //int& ref = 10; 引用本身需要一個合法的內存空間,因此這行錯誤 //加入const就可以了,編譯器優(yōu)化代碼,int temp = 10; const int& ref = temp; const int& ref = 10; //ref = 100; //加入const后不可以修改變量 cout << ref << endl; //函數中利用常量引用防止誤操作修改實參 int a = 10; showValue(a); system("pause"); return 0; }
3 函數提高
3.1 函數默認參數
在C++中,函數的形參列表中的形參是可以有默認值的。
語法:返回值類型 函數名 (參數= 默認值){}
int func(int a, int b = 10, int c = 10) { return a + b + c; } //1. 如果某個位置參數有默認值,那么從這個位置往后,從左向右,必須都要有默認值 //2. 如果函數聲明有默認值,函數實現(xiàn)的時候就不能有默認參數 int func2(int a = 10, int b = 10); int func2(int a, int b) { return a + b; } int main() { cout << "ret = " << func(20, 20) << endl; cout << "ret = " << func(100) << endl; system("pause"); return 0; }
3.2 函數占位參數
C++中函數的形參列表里可以有占位參數,用來做占位,調用函數時必須填補該位置
返回值類型 函數名 (數據類型){}
//函數占位參數 ,占位參數也可以有默認參數 void func(int a, int) { cout << "this is func" << endl; } int main() { func(10,10); //占位參數必須填補 system("pause"); return 0; }
3.3 函數重載
3.3.1 函數重載概述
函數名可以相同,提高復用性
函數重載滿足條件:
同一個作用域下
函數名稱相同
函數參數類型不同 或者 個數不同 或者 順序不同
函數的返回值不可以作為函數重載的條件
//函數重載需要函數都在同一個作用域下 void func() { cout << "func 的調用!" << endl; } void func(int a) { cout << "func (int a) 的調用!" << endl; } void func(double a) { cout << "func (double a)的調用!" << endl; } void func(int a ,double b) { cout << "func (int a ,double b) 的調用!" << endl; } void func(double a ,int b) { cout << "func (double a ,int b)的調用!" << endl; } //函數返回值不可以作為函數重載條件 //int func(double a, int b) //{ // cout << "func (double a ,int b)的調用!" << endl; //} int main() { func(); func(10); func(3.14); func(10,3.14); func(3.14 , 10); system("pause"); return 0; }
4 類和對象
C++面向對象的三大特性為:封裝、繼承、多態(tài)
4.1 封裝
4.1.1 封裝的意義
封裝是C++面向對象三大特性之一
封裝的意義:
將屬性和行為作為一個整體,表現(xiàn)生活中的事物
將屬性和行為加以權限控制
封裝意義一:
在設計類的時候,屬性和行為寫在一起,表現(xiàn)事物
語法: class 類名{ 訪問權限: 屬性 / 行為 };
**示例1:**設計一個圓類,求圓的周長
示例代碼:
//圓周率 const double PI = 3.14; //1、封裝的意義 //將屬性和行為作為一個整體,用來表現(xiàn)生活中的事物 //封裝一個圓類,求圓的周長 //class代表設計一個類,后面跟著的是類名 class Circle { public: //訪問權限 公共的權限 //屬性 int m_r;//半徑 //行為 //獲取到圓的周長 double calculateZC() { //2 * pi * r //獲取圓的周長 return 2 * PI * m_r; } }; int main() { //通過圓類,創(chuàng)建圓的對象 // c1就是一個具體的圓 Circle c1; c1.m_r = 10; //給圓對象的半徑 進行賦值操作 //2 * pi * 10 = = 62.8 cout << "圓的周長為: " << c1.calculateZC() << endl; system("pause"); return 0; }
封裝意義二:
類在設計時,可以把屬性和行為放在不同的權限下,加以控制
訪問權限有三種:
public 公共權限
protected 保護權限
private 私有權限
//三種權限 //公共權限 public 類內可以訪問 類外可以訪問 //保護權限 protected 類內可以訪問 類外不可以訪問 //私有權限 private 類內可以訪問 類外不可以訪問 class Person { //姓名 公共權限 public: string m_Name; //汽車 保護權限 protected: string m_Car; //銀行卡密碼 私有權限 private: int m_Password; public: void func() { m_Name = "張三"; m_Car = "拖拉機"; m_Password = 123456; } }; int main() { Person p; p.m_Name = "李四"; //p.m_Car = "奔馳"; //保護權限類外訪問不到 //p.m_Password = 123; //私有權限類外訪問不到 system("pause"); return 0; }
4.1.2 struct和class區(qū)別
在C++中 struct和class唯一的區(qū)別就在于 默認的訪問權限不同
區(qū)別:
struct 默認權限為公共
class 默認權限為私有
class C1 { int m_A; //默認是私有權限 }; struct C2 { int m_A; //默認是公共權限 }; int main() { C1 c1; c1.m_A = 10; //錯誤,訪問權限是私有 C2 c2; c2.m_A = 10; //正確,訪問權限是公共 system("pause"); return 0; }
4.1.3 成員屬性設置為私有
將所有成員屬性設置為私有,可以自己控制讀寫權限
對于寫權限,我們可以檢測數據的有效性
class Person { public: //姓名設置可讀可寫 void setName(string name) { m_Name = name; } string getName() { return m_Name; } //獲取年齡 int getAge() { return m_Age; } //設置年齡 void setAge(int age) { if (age < 0 || age > 150) { cout << "你個老妖精!" << endl; return; } m_Age = age; } //情人設置為只寫 void setLover(string lover) { m_Lover = lover; } private: string m_Name; //可讀可寫 姓名 int m_Age; //只讀 年齡 string m_Lover; //只寫 情人 }; int main() { Person p; //姓名設置 p.setName("張三"); cout << "姓名: " << p.getName() << endl; //年齡設置 p.setAge(50); cout << "年齡: " << p.getAge() << endl; //情人設置 p.setLover("蒼井"); //cout << "情人: " << p.m_Lover << endl; //只寫屬性,不可以讀取 system("pause"); return 0; }
4.2 對象的初始化和清理
4.2.1 構造函數和析構函數
對象的初始化和清理也是兩個非常重要的安全問題
一個對象或者變量沒有初始狀態(tài),對其使用后果是未知
同樣的使用完一個對象或變量,沒有及時清理,也會造成一定的安全問題
c++利用了構造函數和析構函數解決上述問題,這兩個函數將會被編譯器自動調用,完成對象初始化和清理工作。
對象的初始化和清理工作是編譯器強制要我們做的事情,因此如果我們不提供構造和析構,編譯器會提供
編譯器提供的構造函數和析構函數是空實現(xiàn)。
構造函數:主要作用在于創(chuàng)建對象時為對象的成員屬性賦值,構造函數由編譯器自動調用,無須手動調用。
析構函數:主要作用在于對象銷毀前系統(tǒng)自動調用,執(zhí)行一些清理工作。
構造函數語法:類名(){}
1.構造函數,沒有返回值也不寫void
2.函數名稱與類名相同
3.構造函數可以有參數,因此可以發(fā)生重載
4.程序在調用對象時候會自動調用構造,無須手動調用,而且只會調用一次
析構函數語法: ~類名(){}
1.析構函數,沒有返回值也不寫void
2.函數名稱與類名相同,在名稱前加上符號 ~
3.析構函數不可以有參數,因此不可以發(fā)生重載
4.程序在對象銷毀前會自動調用析構,無須手動調用,而且只會調用一次
4.2.2 構造函數的分類及調用
兩種分類方式:
按參數分為: 有參構造和無參構造
按類型分為: 普通構造和拷貝構造
三種調用方式:
括號法
顯示法
隱式轉換法
//1、構造函數分類 // 按照參數分類分為 有參和無參構造 無參又稱為默認構造函數 // 按照類型分類分為 普通構造和拷貝構造 class Person { public: //無參(默認)構造函數 Person() { cout << "無參構造函數!" << endl; } //有參構造函數 Person(int a) { age = a; cout << "有參構造函數!" << endl; } //拷貝構造函數 Person(const Person& p) { age = p.age; cout << "拷貝構造函數!" << endl; } //析構函數 ~Person() { cout << "析構函數!" << endl; } public: int age; }; //2、構造函數的調用 //調用無參構造函數 void test01() { Person p; //調用無參構造函數 } //調用有參的構造函數 void test02() { //2.1 括號法,常用 Person p1(10); //注意1:調用無參構造函數不能加括號,如果加了編譯器認為這是一個函數聲明 //Person p2(); //2.2 顯式法 Person p2 = Person(10); Person p3 = Person(p2); //Person(10)單獨寫就是匿名對象 當前行結束之后,馬上析構 //2.3 隱式轉換法 Person p4 = 10; // Person p4 = Person(10); Person p5 = p4; // Person p5 = Person(p4); //注意2:不能利用 拷貝構造函數 初始化匿名對象 編譯器認為是對象聲明 //Person p5(p4); } int main() { test01(); //test02(); system("pause"); return 0; }
4.2.3 拷貝構造函數調用時機
C++中拷貝構造函數調用時機通常有三種情況
使用一個已經創(chuàng)建完畢的對象來初始化一個新對象
值傳遞的方式給函數參數傳值
以值方式返回局部對象
class Person { public: Person() { cout << "無參構造函數!" << endl; mAge = 0; } Person(int age) { cout << "有參構造函數!" << endl; mAge = age; } Person(const Person& p) { cout << "拷貝構造函數!" << endl; mAge = p.mAge; } //析構函數在釋放內存之前調用 ~Person() { cout << "析構函數!" << endl; } public: int mAge; }; //1. 使用一個已經創(chuàng)建完畢的對象來初始化一個新對象 void test01() { Person man(100); //p對象已經創(chuàng)建完畢 Person newman(man); //調用拷貝構造函數 Person newman2 = man; //拷貝構造 //Person newman3; //newman3 = man; //不是調用拷貝構造函數,賦值操作 } //2. 值傳遞的方式給函數參數傳值 //相當于Person p1 = p; void doWork(Person p1) {} void test02() { Person p; //無參構造函數 doWork(p); } //3. 以值方式返回局部對象 Person doWork2() { Person p1; cout << (int *)&p1 << endl; return p1; } void test03() { Person p = doWork2(); cout << (int *)&p << endl; } int main() { //test01(); //test02(); test03(); system("pause"); return 0; }
4.2.4 構造函數調用規(guī)則
默認情況下,c++編譯器至少給一個類添加3個函數
1.默認構造函數(無參,函數體為空)
2.默認析構函數(無參,函數體為空)
3.默認拷貝構造函數,對屬性進行值拷貝
構造函數調用規(guī)則如下:
如果用戶定義有參構造函數,c++不在提供默認無參構造,但是會提供默認拷貝構造
如果用戶定義拷貝構造函數,c++不會再提供其他構造函數
4.2.5 深拷貝與淺拷貝
淺拷貝:簡單的賦值拷貝操作
深拷貝:在堆區(qū)重新申請空間,進行拷貝操作
如果屬性有在堆區(qū)開辟的,一定要自己提供拷貝構造函數,防止淺拷貝帶來的問題
class Person { public: //無參(默認)構造函數 Person() { cout << "無參構造函數!" << endl; } //有參構造函數 Person(int age ,int height) { cout << "有參構造函數!" << endl; m_age = age; m_height = new int(height); } //拷貝構造函數 Person(const Person& p) { cout << "拷貝構造函數!" << endl; //如果不利用深拷貝在堆區(qū)創(chuàng)建新內存,會導致淺拷貝帶來的重復釋放堆區(qū)問題 m_age = p.m_age; m_height = new int(*p.m_height); } //析構函數 ~Person() { cout << "析構函數!" << endl; if (m_height != NULL) { delete m_height; } } public: int m_age; int* m_height; }; void test01() { Person p1(18, 180); Person p2(p1); cout << "p1的年齡: " << p1.m_age << " 身高: " << *p1.m_height << endl; cout << "p2的年齡: " << p2.m_age << " 身高: " << *p2.m_height << endl; } int main() { test01(); system("pause"); return 0; }
4.2.6 初始化列表
C++提供了初始化列表語法,用來初始化屬性
構造函數():屬性1(值1),屬性2(值2)… {}
class Person { public: 傳統(tǒng)方式初始化 //Person(int a, int b, int c) { // m_A = a; // m_B = b; // m_C = c; //} //初始化列表方式初始化 Person(int a, int b, int c) :m_A(a), m_B(b), m_C(c) {} void PrintPerson() { cout << "mA:" << m_A << endl; cout << "mB:" << m_B << endl; cout << "mC:" << m_C << endl; } private: int m_A; int m_B; int m_C; }; int main() { Person p(1, 2, 3); p.PrintPerson(); system("pause"); return 0; }
4.2.7 類對象作為類成員
C++類中的成員可以是另一個類的對象,我們稱該成員為 對象成員
例如:
class A {}class B{ A a;}
B類中有對象A作為成員,A為對象成員
class Phone { public: Phone(string name) { m_PhoneName = name; cout << "Phone構造" << endl; } ~Phone() { cout << "Phone析構" << endl; } string m_PhoneName; }; class Person { public: //初始化列表可以告訴編譯器調用哪一個構造函數 Person(string name, string pName) :m_Name(name), m_Phone(pName) { cout << "Person構造" << endl; } ~Person() { cout << "Person析構" << endl; } void playGame() { cout << m_Name << " 使用" << m_Phone.m_PhoneName << " 牌手機! " << endl; } string m_Name; Phone m_Phone; }; void test01() { //當類中成員是其他類對象時,我們稱該成員為 對象成員 //構造的順序是 :先調用對象成員的構造,再調用本類構造 //析構順序與構造相反 Person p("張三" , "蘋果X"); p.playGame(); } int main() { test01(); system("pause"); return 0; }
4.2.8 靜態(tài)成員
靜態(tài)成員就是在成員變量和成員函數前加上關鍵字static,稱為靜態(tài)成員
靜態(tài)成員分為:
靜態(tài)成員變量
所有對象共享同一份數據
在編譯階段分配內存
類內聲明,類外初始化
靜態(tài)成員函數
所有對象共享同一個函數
靜態(tài)成員函數只能訪問靜態(tài)成員變量
靜態(tài)成員變量:
class Person { public: static int m_A; //靜態(tài)成員變量 //靜態(tài)成員變量特點: //1 在編譯階段分配內存 //2 類內聲明,類外初始化 //3 所有對象共享同一份數據 private: static int m_B; //靜態(tài)成員變量也是有訪問權限的 }; int Person::m_A = 10; int Person::m_B = 10; void test01() { //靜態(tài)成員變量兩種訪問方式 //1、通過對象 Person p1; p1.m_A = 100; cout << "p1.m_A = " << p1.m_A << endl; Person p2; p2.m_A = 200; cout << "p1.m_A = " << p1.m_A << endl; //共享同一份數據 cout << "p2.m_A = " << p2.m_A << endl; //2、通過類名 cout << "m_A = " << Person::m_A << endl; //cout << "m_B = " << Person::m_B << endl; //私有權限訪問不到 } int main() { test01(); system("pause"); return 0; }
靜態(tài)成員函數:
class Person { public: //靜態(tài)成員函數特點: //1 程序共享一個函數 //2 靜態(tài)成員函數只能訪問靜態(tài)成員變量 static void func() { cout << "func調用" << endl; m_A = 100; //m_B = 100; //錯誤,不可以訪問非靜態(tài)成員變量 } static int m_A; //靜態(tài)成員變量 int m_B; // private: //靜態(tài)成員函數也是有訪問權限的 static void func2() { cout << "func2調用" << endl; } }; int Person::m_A = 10; void test01() { //靜態(tài)成員變量兩種訪問方式 //1、通過對象 Person p1; p1.func(); //2、通過類名 Person::func(); //Person::func2(); //私有權限訪問不到 } int main() { test01(); system("pause"); return 0; }
4.3 C++對象模型和this指針
4.3.1 成員變量和成員函數分開存儲
在C++中,類內的成員變量和成員函數分開存儲
只有非靜態(tài)成員變量才屬于類的對象上
class Person { public: Person() { mA = 0; } //非靜態(tài)成員變量占對象空間 int mA; //靜態(tài)成員變量不占對象空間 static int mB; //函數也不占對象空間,所有函數共享一個函數實例 void func() { cout << "mA:" << this->mA << endl; } //靜態(tài)成員函數也不占對象空間 static void sfunc() { } }; int main() { cout << sizeof(Person) << endl; system("pause"); return 0; }
4.3.2 this指針概念
通過上面我們知道在C++中成員變量和成員函數是分開存儲的
每一個非靜態(tài)成員函數只會誕生一份函數實例,也就是說多個同類型的對象會共用一塊代碼
c++通過提供特殊的對象指針,this指針,解決上述問題。this指針指向被調用的成員函數所屬的對象
this指針是隱含每一個非靜態(tài)成員函數內的一種指針
this指針不需要定義,直接使用即可
this指針的用途:
當形參和成員變量同名時,可用this指針來區(qū)分
在類的非靜態(tài)成員函數中返回對象本身,可使用return *this
4.3.3 空指針訪問成員函數
C++中空指針也是可以調用成員函數的,但是也要注意有沒有用到this指針
如果用到this指針,需要加以判斷保證代碼的健壯性
4.3.4 const修飾成員函數
常函數:
成員函數后加const后我們稱為這個函數為常函數
常函數內不可以修改成員屬性
成員屬性聲明時加關鍵字mutable后,在常函數中依然可以修改
常對象:
聲明對象前加const稱該對象為常對象
常對象只能調用常函數
class Person { public: Person() { m_A = 0; m_B = 0; } //this指針的本質是一個指針常量,指針的指向不可修改 //如果想讓指針指向的值也不可以修改,需要聲明常函數 void ShowPerson() const { //const Type* const pointer; //this = NULL; //不能修改指針的指向 Person* const this; //this->mA = 100; //但是this指針指向的對象的數據是可以修改的 //const修飾成員函數,表示指針指向的內存空間的數據不能修改,除了mutable修飾的變量 this->m_B = 100; } void MyFunc() const { //mA = 10000; } public: int m_A; mutable int m_B; //可修改 可變的 }; //const修飾對象 常對象 void test01() { const Person person; //常量對象 cout << person.m_A << endl; //person.mA = 100; //常對象不能修改成員變量的值,但是可以訪問 person.m_B = 100; //但是常對象可以修改mutable修飾成員變量 //常對象訪問成員函數 person.MyFunc(); //常對象不能調用const的函數 } int main() { test01(); system("pause"); return 0; }
若本篇內容對您有所幫助,請三連,關注,支持下。
Dragon少年 | 文
C++ 面向對象編程
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。